You are on page 1of 7

New Java features Autoboxing/unboxing

Java 5.0 introduced (at least) three language features This automatically creates an Integer object:
http://java.sun.com/j2se/1.5.0/docs/guide/language/ Integer i1 = 3; // autoboxing
int i2 = i1; // unboxing
Autoboxing/unboxing
Automatically converts primitives (such as int) to wrapper classes (such as
Integer) Note that this doesn’t have a call to intValue:
Enhanced for loop /** Return the sum of the elements in a */
New concise syntax for iterating through a collection public static int sum(Integer[] a) {
int result = 0;
Generics
for (int i = 0; i != a.length; i++) {
Constrain what kinds of objects collections such as Vectors, ArrayLists, result += a[i]; // unboxing
Maps, and Sets can contain }
Removes need for annoying typecasts and instanceof checks return result;
}

Enhanced for loop Enhanced for loop (cont.)

Removes need for indexing: Another example, using an ArrayList instead of an array (this is almost right – we
will correct it in a few slides from now):
/** Return the sum of the elements in a */ /** Return the sum of the elements in a */
public static int sum(Integer[] a) { public static int sum(ArrayList a) {
int result = 0; int result = 0;
for (Integer i : a) { for (Integer v : a) {
result += v;
result += i;
}
} return result;
return result; }
} The old way:
Iterator iter = a.iterator();
while (iter.hasNext()) {
(Sure beats the old way, doesn’t it?) Integer v = (Integer) iter.next();

1
Java: generics Java: generics

Java 1.4: Examples of collections using generics:


When you take something out of a collection (such as java.util.Set<E>, java.util.List<E>
Vector) you must cast it
The <E> specifies a generic type
You can’t say "I want a list of Dates"; instead, you must
work with Objects Can declare Sets and Lists of whatever we want
New feature: generics
Java 1.5 generics: A list that can only hold Strings:
Can specify what type a collection should contain when List<String> a = new ArrayList<String>();
you declare it a.add("Look ma, no cast on the next line");
String result = a.get(0);
Can only insert objects of that type a.add(new Date()); // compile error!
No need to cast when you get them back out

Java: generics Java: generics (cont.)

Iteration using generics, autoboxing, and the new for loop is beautiful (to New safety and ease:
a geek): Can only call sum with lists that contain only Integers
/** Return the sum of the elements in a */
No need for a typecast or a call to intValue
public static int sum(ArrayList<Integer> a) {
No need to create an Iterator
int result = 0;
for (Integer v : a) {
result += v;
}
return result;
}

2
A common problem Solution: maps

Want to associate pairs of values where one of the A list is a function from 0..N-1 to values
values is guaranteed to be unique As a list of pairs:
Example: match people with their favourite chocolate [["Darwin", "Snickers"], ["Newton",
bar "Mars Bar"], ["Turing", "Kit Kat"]]
"Michelle" => "Coffee Crisp" A map is a function from keys to values
"Paul" => "Kit Kat" As a map:
How would we do this with lists? {"Newton"="Mars Bar", "Darwin"=
"Snickers", "Turing"="Kit Kat"}
Note: Maps are unordered

Maps Interface and implementation

Each key can appear at most once and has only one Generic properties of maps defined by interface
value java.util.Map<K, V>: a Java interface that maps keys
of type <K> to values of type <V>
Also called hashes (Perl), dictionaries (Python), and
associative arrays (ancient) Classes implementing Map:
HashMap, TreeMap
Take CSC263H to learn how to choose

3
Putting values in Birthday example

To insert key/value pairs: public class Birthday {


/** public static void main(String[] args) {
* Associate value with key and return the Map<String, Integer> m =
* previous value associated with key, or new HashMap<String, Integer>();
* null if there was no previous mapping. m.put("Newton", 1642);
*/ m.put("Darwin", 1809);
public V put(K key, V value) System.out.println(m);
}
To get a printable version, use toString, which }
uses this format: {Darwin=1809, Newton=1642}
"{key1=value1, key2=value2, …}"

Getting values out Iterating


To retrieve the value associated with a key:
/**
Often iterate by getting the set of keys, and iterating
* Return the value associated with key, over that
* or null if the key is not in the map. Set<String> keys = m.keySet();
*/
Iterator<String> i = keys.iterator();
public V get(Object key)
while (i.hasNext()) {
To check whether a key is in the map: String key = i.next();
/** System.out.println
* Return true if the map contains a value (key + "=>" + m.get(key));
* associated with key }
*/
Darwin=>1809
public boolean containsKey(Object key)
Newton=>1642

4
Iterate using new for loop Lookup table
public static void main(String[] args) {
Or, using the new for loop:
Map m = new HashMap();
Set<String> keys = m.keySet(); for (int i = 0; i < data.length; ++i) {
for (String key : keys) { String[] fields = data[i].split(" ");
System.out.println( m.put(fields[0], fields[1]);
}
key + "=>" + m.get(key));
} System.out.println("Darwin: " + m.get("Darwin"));
System.out.println("Newton: " + m.get("Newton"));
System.out.println("Turing: " + m.get("Turing"));
}

Counting Inverting
public static void main(String[] args) { public static void main(String[] args) {
String[] data = "Be Mg Mg Ca Be Mg".split(" "); Map byName = new HashMap();
Map<String, Integer> m = new HashMap<String, Integer>(); byName.put("Darwin", "748-2797");

for (String d : data) { byName.put("Newton", "748-9901");


Map byPhone = new HashMap();
if (!m.containsKey(d)) {
Iterator i = byName.entrySet().iterator();
m.put(d, 1);
while (i.hasNext()) {
} else {
Map.Entry e = (Map.Entry) i.next();
m.put(d, m.get(d) + 1); byPhone.put(e.getValue(), e.getKey());
} }
} System.out.println(byPhone);
System.out.println(m); } {748-2797=Darwin, 748-9901=Newton}
} {Ca=1, Mg=3, Be=2}

5
Inverting (Java 5.0) Caution #1
public static void main(String[] args) {
Do not modify key objects: location in map is
Map<String, String> byName =
new HashMap<String, String>();
computed from key contents ("hash code")
byName.put("Darwin", "748-2797"); Can't change Strings
byName.put("Newton", "748-9901"); But, you can change sets, lists, etc.
Map<String, String> byPhone =
What happens if you do?
new HashMap<String, String>();
for (Map.Entry<String, String> e : byName.entrySet()) { Entry is now filed in the wrong location
byPhone.put(e.getValue(), e.getKey()); May not be found the next time you search
} Very hard to track down
System.out.println(byPhone);
} {748-2797=Darwin, 748-9901=Newton}

Caution #2 Reminder: input/output

If you override method equals, override hashCode There are three file-like objects associated with every
as well program:
a == b iff a and b are the same object stdin – standard input, usually from the keyboard
a.equals(b) checks to see if a and b refer to objects (System.in)
that have the same value
stdout – standard output, usually to the screen
If a.equals(b), then a.hashCode() and (System.out)
b.hashCode() must return the same value
stderr – standard error, usually to the screen
Why? Because that's how maps do lookups (System.err)

6
Reminder: I/O Trick: reading from Strings
BufferedReader input;
We can use the same file abstraction to read from
input = new BufferedReader(new FileReader("filename"));
strings (and print to them):
input = new BufferedReader(new InputStreamReader(System.in)); input = new BufferedReader(
new StringReader("A string"));
String line;
while((line = input.readLine()) != null) { Primary advantage is for testing
// do something
}
We can keep all test code in a single file, but use the
same interfaces
It is a lot faster
You’ll see this technique used in E1

You might also like