320 likes | 450 Views
CS 340 Data Structures. Lecture: Arrays, Collections. Today’s Topics. More on arrays Shallow copies, deep copies, and cloning Sorting & searching in arrays Introduction to containers. Arrays.
E N D
CS 340 Data Structures Lecture: Arrays, Collections
Today’s Topics • More on arrays • Shallow copies, deep copies, and cloning • Sorting & searching in arrays • Introduction to containers
Arrays • An array is a “first-class object,” unlike a C/C++ array, which is just a bunch of contiguous memory locations. • As for all objects, the array name is a reference to the actual object. • This object has space sufficient for • the number of references you specify, if your array holds objects, or • the number of primitive values you specify, if your array holds primitive types, • plus space to hold the array length.
Arrays of Primitives int[] a = new int[3]; // compiler does initialization 0 0 0 3 This is schematic only, e.g., length may not be first in memory. a.length a[0] a[1] a[2] int[] a = {41, 32, 19}; // compiler does initialization 32 41 19 3 a.length a[0] a[1] a[2]
Arrays of Primitives (cont.) • Here are two common (compile) errors: • But this is OK: int[] a; a[2] = 5; // a uninitialized int[] b; int len = b.length; // b uninitialized int[] a = {41, 32, 19}; int[] b; b = a; int len = b.length;
Arrays of Objects class Stock { int sharesHeld = 0; double currentPrice = 100.00; } Stock[] a = new Stock[3]; // initialization to 3 The array components a[0], a[1] and a[2] are null () references. a a.length a[0] a[1] a[2]
Arrays of Objects for (int i = 0; i < 3; i++) a[i] = new Stock(); f12 f0 f24 3 Stock Stock Stock a a.length a[0] a[1] a[2]
Passing Arrays to Methods public class Stock { Stock() {} Stock(int s, double p, String name) { sharesHeld = s; currentPrice = p; symbol = name; } int sharesHeld = 0; double currentPrice = 100.00; String symbol; public String toString() { String s = new String(); s += sharesHeld + " shares of " + symbol + " at $" + currentPrice; return s; } }
Investor public class Investor { Stock[] portfolio; Advisor ohTrustedOne; double value; Investor() {portfolio = new Stock[0];} Investor(Stock[] p, Advisor a) { portfolio = p; ohTrustedOne = a; value = ohTrustedOne.findValue(p); } // more below
Investor (cont.) String describePortfolio() { String s = new String(); s += "My portfolio is: \n"; for (int i = 0; i < portfolio.length; i++) s += portfolio[i] + "\n"; s += "The total value is $" + value; return s; } void askAdvice() { ohTrustedOne.advise(portfolio); } }
Advisor public class Advisor { double findValue(Stock[] p) { double value = 0; for (int i = 0; i < p.length; i++) value += p[i].currentPrice * p[i].sharesHeld; return value; } void advise(Stock[] p) { swindle(p); } void swindle(Stock[] p) { for (int i = 0; i < p.length; i++) p[i].sharesHeld /= 2; } }
Test Passing Arrays public class TestInvestments { public static void main(String[] args) { Stock[] p = new Stock[] {new Stock(1000, 53.45, "GnMotr"), new Stock(100, 29.05, "GenElec"), new Stock(220, 44.08, "GenMills")}; Advisor deweyCheethamAndHowe = new Advisor(); Investor sucker = new Investor(p, deweyCheethamAndHowe); System.out.println(sucker.describePortfolio()); sucker.askAdvice(); System.out.println(sucker.describePortfolio()); } }
Dangers in Passing Arrays • The called method gets a reference to the actual array, and can modify it. • Using final is a possibility, but not in this example (at least not easily). • If you are cautious, you can make a copy and send that.
Copies of Arrays • Shallowest: make a copy of the array reference • Shallow: make a new array of references of the same type and size, and copy into it the existing array of references • Deep: the above, plus make copies of all the objects themselves • The method System.arraycopy() does a shallow copy—arghhh!
Deep Copy of an Array Stock[] copyPortfolio() { // illustrates returning an array Stock[] copy = new Stock[portfolio.length]; for (int i = 0; i < portfolio.length; i++) { Stock s = new Stock(); s.currentPrice = portfolio[i].currentPrice; s.sharesHeld = portfolio[i].sharesHeld; s.symbol = new String(portfolio[i].symbol); copy[i] = s; } return copy; }
Aside: Cloning • Java doesn’t have the equivalent of C++’s copy constructor, but does have cloning. • If a class implements the Cloneable interface, then you can make a “duplicate copy” by calling clone(). • To implement, override Object’s clone() method as a public method in your class. • clone() returns an Object, which you can then cast to the correct type.
Cloning Example public class SimpleObject implements Cloneable { private int i; SimpleObject(int i) {this.i = i;} public String toString() { String s = new String(); s += "I'm a SimpleObject with i = " + i; s += " and address " + super.toString(); return s; }
Cloning Example (cont.) public Object clone() { Object o = null; try { o = super.clone(); } catch(CloneNotSupportedException e) { System.out.println("SimpleClass can't clone."); } return o; } }
Cloning Example (cont.) public class CloneTest { public static void main(String[] args) { SimpleObject s1 = new SimpleObject(1); System.out.println(s1); SimpleObject s2 = (SimpleObject) s1.clone(); System.out.println(s2); } } One run produces this: I'm a SimpleObject with i = 1 and address SimpleObject@158269a I'm a SimpleObject with i = 1 and address SimpleObject@15829aa
Arrays Are “Type-Safe” • You explicitly declare the type of objects held in the array. • The compiler checks to make sure your usage agrees with your declaration. • A very common usage is to write a class hierarchy, then use an array of the type “highest” in the hierarchy (an array of Nodes, for example). • Polymorphism is then used to work with the array elements.
The Arrays Class • In java.util • Provides many versions of the static methods: • asList() • binarySearch() • equals() • fill() • sort() Versions of these for byte, char, double, float, int, long, Object and short. The Object versions of binarySearch() and sort() allow you to specify a comparator.
Sorting Students public static void main(String[] args) { Student s1 = new Student("Fred", 3.0F); Student s2 = new Student("Sam", 3.5F); Student s3 = new Student("Steve", 2.1F); Student[] students = new Student[] {s1, s2, s3}; for (int i = 0; i < students.length; i++) System.out.println(students[i].getName() + "\t" + students[i].getGpa()); Arrays.sort(students); for (int i = 0; i < students.length; i++) System.out.println(students[i].getName() + "\t" + students[i].getGpa()); }
Sorting Students (cont.) • This gives, as expected, the following: This example used the natural comparison methodcompareTo() that we provided in the Student class (which implemented the Comparable interface). That comparison method compared gpas. sort() also allows you to specify a different comparison method if you want… Fred 3.0 Sam 3.5 Steve 2.1 Steve 2.1 Fred 3.0 Sam 3.5
Sorting With a Comparator • The Comparator interface allows you to define “objects that know how to compare two things.” • This interface expects you to define the compare() method (and perhaps also the equals() method). • Let’s try it for Students.
Student Comparator import java.util.*; public class CompareStudentNames implements Comparator { public int compare(Object s1, Object s2) { return ((Student) s1).getName().compareTo( ((Student) s2).getName()); } }
Let’s Try It Student s1 = new Student("Sam", 3.5F); // note I changed Student s2 = new Student("Steve", 2.1F); // the order of Student s3 = new Student("Fred", 3.0F); // the students! Student[] students = new Student[] {s1, s2, s3}; for (int i = 0; i < students.length; i++) System.out.println(students[i].getName() + "\t" + students[i].getGpa()); Arrays.sort(students, new CompareStudentNames()); for (int i = 0; i < students.length; i++) System.out.println(students[i].getName() + "\t" + students[i].getGpa());
Now Try Filling Arrays.fill(students, s1); for (int i = 0; i < students.length; i++) System.out.println(students[i].getName() + "\t" + students[i].getGpa()); students[1].setName("Gautam"); for (int i = 0; i < students.length; i++) System.out.println(students[i].getName() + "\t" + students[i].getGpa()); This gives: Fred 3.0 Fred 3.0 Fred 3.0 Gautam 3.0 Gautam 3.0 Gautam 3.0 This is probably not what we want!
The Java Container Classes • A container class object could be • your bookcase • your photo album • your suitcase • your “junk drawer” in the kitchen • your apartment • Containers hold Object references, so can be dangerous. • We can learn to live with danger…
Container Classes: Collection • List and Set, essentially, with some specializations. They store individual objects, and give you • add(Object) • remove(Object) • contains(Object) • size() • other methods too
Container Classes: Map • These hold pairs of things, a key and a value. • Pairs are held in a map, ordered by the key • Methods include • containsKey(Object key) • containsValue(Object value) • put(Object key, Object value) • get(Object key) • remove(Object key)