Day 3 Hashing, Collections, And: Comparators
Day 3 Hashing, Collections, And: Comparators
Hashing, Collections,
and Comparators
Hashing
Yesterday
we overrode .equals()
Today
we override .hashCode()
Goal:
What is a Hash?
An
Quick
way to check for inequality, construct groupings things (should) have equal hashs
Equal
What is .hashCode()
Well
Is
defined in java.lang.Object to return a value mostly unique to that instance classes either inherit it, or override it
All
An
objects hashcode cannot change until it is no longer equal to what it was equal objects must have an equal hashCode is good if two unequal objects have distinct hashes
Two
It
Hashcode Examples
public class Name { public String first; public String last; public Name(String first, String last) {
this.first = first;
this.last = last;
} public String toString() {
return first + " " + last;
}
public boolean equals(Object o) {
return (o instanceof Name && ((Name) o).first.equals(this.first) && ((Name) o).last.equals(this.last)); }}
Name kyle = new Name(Kyle, MacLaughlin); Name jack = new Name("Jack", "Nance"); Name jack2 = new Name("Jack", "Nance"); System.out.println(kyle.equals(jack)); System.out.println(jack.equals(jack2)); System.out.println(kyle.hashCode()); System.out.println(jack.hashCode()); System.out.println(jack2.hashCode()); false, true, 6718604, 7122755, 14718739
Name
Is
If
We
We
hashCode() must obey equality hashCode() must be consistent hashCode() must generate int hashCode() should recognize inequality
Possible Implementation
Set<Name> names = new HashSet<Name>() names.add(jack); System.out.println(names.contains( new Name(Jack, Nance)); true
Could it be better?
A Better Implementation
An
objects hashcode cannot change until it is no longer equal to what it was equal objects must have an equal hashCode is good if two unequal objects have distinct hashes
Two
It
Any
It
It
What Collections Do
Framework
handle:
Collecting objects
Storing objects Sorting objects Retrieving objects
Provides
add
file
Example Usage
List<Name> iapjava = new ArrayList<Name>(); iapjava.add(new Name(Laura, Dern); iapjava.add(new Name(Toby, Keeler); System.out.println(iapjava.size()); => 2 iapjava.remove(new Name(Toby, Keeler); System.out.println(iapjava.size()); => 1 List<Name> iapruby = new ArrayList<Name>(); Iapruby.add(new Name(Scott, Ostler)); iapjava.addAll(iapruby); System.out.println(iapjava.size()); => 2
Generic Collections
We
can specify the type of object that a collection will hold List<String> strings
Ex: We
are reasonably sure that strings contains only String objects optional, but very useful
Is
Retrieving objects
For each:
for (Foo obj : coll) { // do something with obj }
Note that iter.remove is optional, and not all Iterator objects will support it
List
ArrayList HashSet
TreeSet
HashMap
Set
Map
List Overview
Other Ways
Insert at an index
List<String> strings = new ArrayList<String>(); strings.add(one); strings.add(three); strings.add(1, two); // strings = [ one, two, three]
Set Overview
Set<Name> names = new HashSet<Name>(); names.add(new Name(Jack, Nance)); names.add(new Name(Jack, Nance)); System.out.println(names.size()); => 1
Set Contract
set element cannot be changed in a way that affects its equality is a danger of object mutability
This
If
you dont obey the contract, prepare for Bad, Strange Things
Set<Name> names = new HashSet<Name>(); Name jack = new Name(Jack, Nance); names.add(jack); System.out.println(names.size()); System.out.println(names.contains(jack)); => true; jack.last = "Vance"; System.out.println(names.contains(jack)); => false System.out.println(names.size()); => 1
Map Overview
Mapping That
is, for every Key object, there is a Value object a lookup service
Essentially Keys
to be
Rather, it supports:
Map<String, String> dns = new HashMap<String, String>(); dns.put(scotty.mit.edu, 18.227.0.87); System.out.println(dns.get(scotty.mit.edu)); System.out.println(dns.containsKey(scotty.mit.edu)); System.out.println(dns.containsValue(18.227.0.87)); dns.remove(scotty.mit.edu); System.out.println(dns.containsValue(18.227.0.87)); // => 18.227.0.87, true, true, false
keySet() - returns a Set of all the keys values() - returns a Collection of all the values
entrySet() - returns a Set of Key,Value Pairs
This
If
What happens?
Two Answers
Right
Answer:
Righter Answer:
We
want to be able to use any object to stand in for another mutable objects are dangerous
But
Name dennis = new Name(Dennis, Hopper); Name copy = new Name(dennis.first, dennis.last); map.put(copy, 555-555-1234);
public class Name { public final String first; public final String last; public Name(String first, String last) {
this.first = first;
this.last = last;
} public boolean equals(Object o) { return (o instanceof Name && ((Name) o).first.equals(this.first) && ((Name) o).last.equals(this.last)); }}
Freeze Keys
public class Name { private String first; private String last; private boolean frozen = false; public void setFirst(String s) { if (!frozen) first = s; } // do same with setLast public void freeze() { frozen = true; } }
Each
Collection Wrap-up
Common problems
Sharing obects between Collections Trying to remove an Object during iteration Mutable Keys, Sets
Any questions?
Used
to decide, between two objects, if one is bigger or they are equal should result in:
(a.compareTo(b))
Comparison Example
Integer one = 1; System.out.println(one.compareTo(3)); System.out.println(one.compareTo(-50)); String frank = Frank; System.out.println(frank.compareTo(Booth)); System.out.println(frank.compareTo(Hopper)); // => -1 , 1, 4, -2
Comparable Interface
We
can sort Strings because they implement Comparable That is, they have a Natural Ordering.
To make Foo class Comparable, we have to implement:
A Sortable Name
List<Name> names = new ArrayList<Name>(); names.add(new Name("Nicolas", "Cage")); names.add(new Name("Laura", "Dern")); names.add(new Name("Harry", "Stanton")); names.add(new Name("Diane", "Ladd")); names.add(new Name("William", "Morgan")); names.add(new Name(Dirty, "Glover")); names.add(new Name("Johnny", "Cage")); names.add(new Name("Metal", "Cage")); System.out.println(names); Collections.sort(names); System.out.println(names); // => [Johnny Cage, Metal Cage, Nicolas Cage, Laura Dern, Crispin Glover, Diane Ladd, William Morgan, Harry Stanton]
Comparator Objects
To
create multiple sortings for a given Type, we can define Comparator classes A Comparator takes in two objects, and determines which is bigger For type Foo, a Comparator<Foo> has:
int compare(Foo o1, Foo o2);
A First-Name-First Comparator
public class FirstNameFirst implements Comparator<Name> { public int compare(Name n1, Name n2) { int ret = n1.first.compareTo(n2.first); if (ret != 0) return ret; else return n1.last.compareTo(n2.last); } } This goes in a separate file, FirstNameFirst.java
Does it Work?
It works!
Comparison Contract
Once
follow
Specifically,
be careful when
such a sorting, using SortedSet or SortedMap will cause Bad, Strange Things
Either the Objects in TreeSet must implement Comparable Or give a Comparator Object when making the TreeSet
SortedSet<Name> names = new TreeSet<Name>(new FirstNameFirst()); names.add(new Name("Laura", "Dern")); names.add(new Name("Harry", "Stanton")); names.add(new Name("Diane", "Ladd")); System.out.println(names); // => [Diane Ladd, Harry Stanton, Laura Dern]
Day 3 Wrap-Up
Ask
questions!
There was more here than anyone could get or remember Think of what you want your code to do, and the best way to express that Read Suns Java Documentation:
http://java.sun.com/j2se/1.5.0/docs/api
No one can keep Java in their head Everytime you code, have this page open