Thinking in Java 4th Edition phần 7 pdf

108 460 0
Thinking in Java 4th Edition phần 7 pdf

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

 print("Produced 0.0!"); } else if(args[0].equals("upper")) { while(Math.random() != 1.0) ; // Keep trying print("Produced 1.0!"); } else usage(); } } ///:~ To run the program, you type a command line of either: java RandomBounds lower or java RandomBounds upper In both cases, you are forced to break out of the program manually, so it would appear that Math.random( ) never produces either o.o or l.o. But this is where such an experiment can be deceiving. If you consider that there are about 262 different double fractions between o and 1, the likelihood of reaching any one value experimentally might exceed the lifetime of one computer, or even one experimenter. It turns out that 0.0 is included in the output of Math.random( ). Or, in math lingo, it is [0,1). Thus, you must be careful to analyze your experiments and to understand their limitations. Choosing between Sets Depending on the behavior you desire, you can choose a TreeSet, a HashSet, or a LinkedHashSet. The following test program gives an indication of the performance trade- off between these implementations: //: containers/SetPerformance.java // Demonstrates performance differences in Sets. // {Args: 100 5000} Small to keep build testing short import java.util.*; public class SetPerformance { static List<Test<Set<Integer>>> tests = new ArrayList<Test<Set<Integer>>>(); static { tests.add(new Test<Set<Integer>>("add") { int test(Set<Integer> set, TestParam tp) { int loops = tp.loops; int size = tp.size; for(int i = 0; i < loops; i++) { set.clear(); for(int j = 0; j < size; j++) set.add(j); } return loops * size; } }); tests.add(new Test<Set<Integer>>("contains") { int test(Set<Integer> set, TestParam tp) { int loops = tp.loops; Containers in Depth 627 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com  int span = tp.size * 2; for(int i = 0; i < loops; i++) for(int j = 0; j < span; j++) set.contains(j); return loops * span; } }); tests.add(new Test<Set<Integer>>("iterate") { int test(Set<Integer> set, TestParam tp) { int loops = tp.loops * 10; for(int i = 0; i < loops; i++) { Iterator<Integer> it = set.iterator(); while(it.hasNext()) it.next(); } return loops * set.size(); } }); } public static void main(String[] args) { if(args.length > 0) Tester.defaultParams = TestParam.array(args); Tester.fieldWidth = 10; Tester.run(new TreeSet<Integer>(), tests); Tester.run(new HashSet<Integer>(), tests); Tester.run(new LinkedHashSet<Integer>(), tests); } } /* Output: (Sample) TreeSet size add contains iterate 10 746 173 89 100 501 264 68 1000 714 410 69 10000 1975 552 69 HashSet size add contains iterate 10 308 91 94 100 178 75 73 1000 216 110 72 10000 711 215 100 LinkedHashSet size add contains iterate 10 350 65 83 100 270 74 55 1000 303 111 54 10000 1615 256 58 *///:~ The performance of HashSet is generally superior to TreeSet, but especially when adding elements and looking them up, which are the two most important operations. TreeSet exists because it maintains its elements in sorted order, so you use it only when you need a sorted Set. Because of the internal structure necessary to support sorting and because iteration is something you’re more likely to do, iteration is usually faster with a TreeSet than a HashSet. Note that LinkedHashSet is more expensive for insertions than HashSet; this is because of the extra cost of maintaining the linked list along with the hashed container. Exercise 34: (1) Modify SetPerformance.java so that the Sets hold String objects instead of Integers. Use a Generator from the Arrays chapter to create test values. 628 Thinking in Java Bruce Eckel Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com  Choosing between Maps This program gives an indication of the trade-off between Map implementations: //: containers/MapPerformance.java // Demonstrates performance differences in Maps. // {Args: 100 5000} Small to keep build testing short import java.util.*; public class MapPerformance { static List<Test<Map<Integer,Integer>>> tests = new ArrayList<Test<Map<Integer,Integer>>>(); static { tests.add(new Test<Map<Integer,Integer>>("put") { int test(Map<Integer,Integer> map, TestParam tp) { int loops = tp.loops; int size = tp.size; for(int i = 0; i < loops; i++) { map.clear(); for(int j = 0; j < size; j++) map.put(j, j); } return loops * size; } }); tests.add(new Test<Map<Integer,Integer>>("get") { int test(Map<Integer,Integer> map, TestParam tp) { int loops = tp.loops; int span = tp.size * 2; for(int i = 0; i < loops; i++) for(int j = 0; j < span; j++) map.get(j); return loops * span; } }); tests.add(new Test<Map<Integer,Integer>>("iterate") { int test(Map<Integer,Integer> map, TestParam tp) { int loops = tp.loops * 10; for(int i = 0; i < loops; i ++) { Iterator it = map.entrySet().iterator(); while(it.hasNext()) it.next(); } return loops * map.size(); } }); } public static void main(String[] args) { if(args.length > 0) Tester.defaultParams = TestParam.array(args); Tester.run(new TreeMap<Integer,Integer>(), tests); Tester.run(new HashMap<Integer,Integer>(), tests); Tester.run(new LinkedHashMap<Integer,Integer>(),tests); Tester.run( new IdentityHashMap<Integer,Integer>(), tests); Tester.run(new WeakHashMap<Integer,Integer>(), tests); Tester.run(new Hashtable<Integer,Integer>(), tests); } } /* Output: (Sample) TreeMap size put get iterate Containers in Depth 629 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com  10 748 168 100 100 506 264 76 1000 771 450 78 10000 2962 561 83 HashMap size put get iterate 10 281 76 93 100 179 70 73 1000 267 102 72 10000 1305 265 97 LinkedHashMap size put get iterate 10 354 100 72 100 273 89 50 1000 385 222 56 10000 2787 341 56 IdentityHashMap size put get iterate 10 290 144 101 100 204 287 132 1000 508 336 77 10000 767 266 56 WeakHashMap size put get iterate 10 484 146 151 100 292 126 117 1000 411 136 152 10000 2165 138 555 Hashtable size put get iterate 10 264 113 113 100 181 105 76 1000 260 201 80 10000 1245 134 77 *///:~ Insertions for all the Map implementations except for IdentityHashMap get significantly slower as the size of the Map gets large. In general, however, lookup is much cheaper than insertion, which is good because you’ll typically be looking items up much more often than you insert them. Hashtable performance is roughly the same as HashMap. Since HashMap is intended to replace Hashtable, and thus uses the same underlying storage and lookup mechanism (which you will learn about later), this is not too surprising. A TreeMap is generally slower than a HashMap. As with TreeSet, a TreeMap is a way to create an ordered list. The behavior of a tree is such that it’s always in order and doesn’t have to be specially sorted. Once you fill a TreeMap, you can call keySet( ) to get a Set view of the keys, then toArray( ) to produce an array of those keys. You can then use the static method Arrays.binarySearch( ) to rapidly find objects in your sorted array. Of course, this only makes sense if the behavior of a HashMap is unacceptable, since HashMap is designed to rapidly find keys. Also, you can easily create a HashMap from a TreeMap with a single object creation or call to putAll( ). In the end, when you’re using a Map, your first choice should be HashMap, and only if you need a constantly sorted Map will you need TreeMap. LinkedHashMap tends to be slower than HashMap for insertions because it maintains the linked list (to preserve insertion order) in addition to the hashed data structure. Because of this list, iteration is faster. 630 Thinking in Java Bruce Eckel Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com  Containers in Depth 631 IdentityHashMap has different performance because it uses == rather than equals( ) for comparisons. WeakHashMap is described later in this chapter. Exercise 35: (1) Modify MapPerformance.java to include tests of SlowMap. Exercise 36: (5) Modify SlowMap so that instead of two ArrayLists, it holds a single ArrayList of MapEntry objects. Verify that the modified version works correctly. Using MapPerformance.java, test the speed of your new Map. Now change the put( ) method so that it performs a sort( ) after each pair is entered, and modify get( ) to use Collections.binarySearch( ) to look up the key. Compare the performance of the new version with the old ones. Exercise 37: (2) Modify SimpleHashMap to use ArrayLists instead of LinkedLists. Modify MapPerformance.java to compare the performance of the two implementations. HashMap performance factors It’s possible to hand-tune a HashMap to increase its performance for your particular application. So that you can understand performance issues when tuning a HashMap, some terminology is necessary: Capacity: The number of buckets in the table. Initial capacity: The number of buckets when the table is created. HashMap and HashSet have constructors that allow you to specify the initial capacity. Size: The number of entries currently in the table. Load factor: Size/capacity. A load factor of o is an empty table, 0.5 is a half-full table, etc. A lightly loaded table will have few collisions and so is optimal for insertions and lookups (but will slow down the process of traversing with an iterator). HashMap and HashSet have constructors that allow you to specify the load factor, which means that when this load factor is reached, the container will automatically increase the capacity (the number of buckets) by roughly doubling it and will redistribute the existing objects into the new set of buckets (this is called rehashing). The default load factor used by HashMap is 0.75 (it doesn’t rehash until the table is three- fourths full). This seems to be a good trade-off between time and space costs. A higher load factor decreases the space required by the table but increases the lookup cost, which is important because lookup is what you do most of the time (including both get( ) and put( )). If you know that you’ll be storing many entries in a HashMap, creating it with an appropriately large initial capacity will prevent the overhead of automatic rehashing. 11 Exercise 38: (3) Look up the HashMap class in the JDK documentation. Create a HashMap, fill it with elements, and determine the load factor. Test the lookup speed with this map, then attempt to increase the speed by making a new HashMap with a larger initial capacity and copying the old map into the new one, then run your lookup speed test again on the new map.  11 In a private message, Joshua Bloch wrote: " I believe that we erred by allowing implementation details (such as hash table size and load factor) into our APIs. The client should perhaps tell us the maximum expected size of a collection, and we should take it from there. Clients can easily do more harm than good by choosing values for these parameters. As an extreme example, consider Vector’s capacitylncrement. No one should ever set this, and we shouldn’t have provided it. If you set it to any nonzero value, the asymptotic cost of a sequence of appends goes from linear to quadratic. In other words, it destroys your performance. Over time, we’re beginning to wise up about this sort of thing. If you look at IdentityHashMap, you’ll see that it has no low-level tuning parameters." Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com  Exercise 39: (6) Add a private rehash( ) method to SimpleHashMap that is invoked when the load factor exceeds 0.75. During rehashing, double the number of buckets, then search for the first prime number greater than that to determine the new number of buckets. Utilities There are a number of standalone utilities for containers, expressed as static methods inside the java.util.Collections class. You’ve already seen some of these, such as addAll( ), reverseOrder( ) and binarySearch( ). Here are the others (the synchronized and unmodifiable utilities will be covered in sections that follow). In this table, generics are used when they are relevant: checkedCollection( Collection<T>, Class<T> type) checkedList( List<T>, Class<T> type) checkedMap(Map<K,V>, Class <K> keyType, Class <V> valueType) checkedSet(Set<T>, Class<T> type) checkedSortedMap( SortedMap<K,V>, Class<K> keyType, Class <V> valueType) checkedSortedSet( SortedSet<T>, Class<T> type) Produces a dynamically type-safe view of a Collection, or a specific subtype of Collection. Use this when it’s not possible to use the statically checked version. These were shown in the Generics chapter under the heading "Dynamic type safety." max(Collection) min(Collection) Produces the maximum or minimum element in the argument using the natural comparison method of the objects in the Collection. max(Collection, Comparator) min(Collection, Comparator) Produces the maximum or minimum element in the Collection using the Comparator. indexOfSubList(List source, List target) Produces starting index of the first place where target appears inside source, or -1 if none occurs. lastIndexOfSubList(List source, List target) Produces starting index of the last place where target appears inside source, or -1 if none occurs. replaceAll(List<T>, T oldVal, T newVal) Replaces all oldVal with newVal. reverse(List) Reverses all the elements in place. reverseOrder( ) reverseOrder( Comparator<T>) Returns a Comparator that reverses the natural ordering of a collection of objects that implement Comparable<T>. The second version reverses the order of the supplied Comparator. 632 Thinking in Java Bruce Eckel Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com  rotate(List, int distance) Moves all elements forward by distance, taking the ones off the end and placing them at the beginning. shuffle(List) shuffle(List, Random) Randomly permutes the specified list. The first form provides its own randomization source, or you may provide your own with the second form. sort(List<T>) sort(List<T>, Comparator<? super T> c) Sorts the List<T> using its natural ordering. The second form allows you to provide a Comparator for sorting. copy(List<? super T> dest, List<? extends T> src) Copies elements from src to dest. swap(List, int i, int j) Swaps elements at locations i and j in the List. Probably faster than what you’d write by hand. fill(List<? super T>, T x) Replaces all the elements of list with x. nCopies(int n, T x) Returns an immutable List<T> of size n whose references all point to x. disjoint(Collection, Collection) Returns true if the two collections have no elements in common. frequency(Collection, Object x) Returns the number of elements in the Collection equal to x. emptyList( ) emptyMap( ) emptySet( ) Returns an immutable empty List, Map, or Set. These are generic, so the resulting Collection will be parameterized to the desired type. singleton(T x) singletonList(T x) singletonMap(K key, V value) Produces an immutable Set<T>, List<T>, or Map<K,V> containing a single entry based on the given argument(s). list(Enumeration<T> e) Produces an ArrayList<T> containing the elements in the order in which they are returned by the (old-style) Enumeration (predecessor to the Iterator). For converting from legacy code. enumeration(Collection<T>) Produces an old-style Enumeration<T> for the argument. Note that min( ) and max( ) work with Collection objects, not with Lists, so you don’t need to worry about whether the Collection should be sorted or not. (As mentioned earlier, you do need to sort( ) a List or an array before performing a binarySearch( ).) Here’s an example showing the basic use of most of the utilities in the above table: Containers in Depth 633 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com  //: containers/Utilities.java // Simple demonstrations of the Collections utilities. import java.util.*; import static net.mindview.util.Print.*; public class Utilities { static List<String> list = Arrays.asList( "one Two three Four five six one".split(" ")); public static void main(String[] args) { print(list); print("‘list’ disjoint (Four)?: " + Collections.disjoint(list, Collections.singletonList("Four"))); print("max: " + Collections.max(list)); print("min: " + Collections.min(list)); print("max w/ comparator: " + Collections.max(list, String.CASE_INSENSITIVE_ORDER)); print("min w/ comparator: " + Collections.min(list, String.CASE_INSENSITIVE_ORDER)); List<String> sublist = Arrays.asList("Four five six".split(" ")); print("indexOfSubList: " + Collections.indexOfSubList(list, sublist)); print("lastIndexOfSubList: " + Collections.lastIndexOfSubList(list, sublist)); Collections.replaceAll(list, "one", "Yo"); print("replaceAll: " + list); Collections.reverse(list); print("reverse: " + list); Collections.rotate(list, 3); print("rotate: " + list); List<String> source = Arrays.asList("in the matrix".split(" ")); Collections.copy(list, source); print("copy: " + list); Collections.swap(list, 0, list.size() - 1); print("swap: " + list); Collections.shuffle(list, new Random(47)); print("shuffled: " + list); Collections.fill(list, "pop"); print("fill: " + list); print("frequency of ‘pop’: " + Collections.frequency(list, "pop")); List<String> dups = Collections.nCopies(3, "snap"); print("dups: " + dups); print("‘list’ disjoint ‘dups’?: " + Collections.disjoint(list, dups)); // Getting an old-style Enumeration: Enumeration<String> e = Collections.enumeration(dups); Vector<String> v = new Vector<String>(); while(e.hasMoreElements()) v.addElement(e.nextElement()); // Converting an old-style Vector // to a List via an Enumeration: ArrayList<String> arrayList = Collections.list(v.elements()); print("arrayList: " + arrayList); } } /* Output: [one, Two, three, Four, five, six, one] ‘list’ disjoint (Four)?: false max: three min: Four 634 Thinking in Java Bruce Eckel Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com  max w/ comparator: Two min w/ comparator: five indexOfSubList: 3 lastIndexOfSubList: 3 replaceAll: [Yo, Two, three, Four, five, six, Yo] reverse: [Yo, six, five, Four, three, Two, Yo] rotate: [three, Two, Yo, Yo, six, five, Four] copy: [in, the, matrix, Yo, six, five, Four] swap: [Four, the, matrix, Yo, six, five, in] shuffled: [six, matrix, the, Four, Yo, five, in] fill: [pop, pop, pop, pop, pop, pop, pop] frequency of ‘pop’: 7 dups: [snap, snap, snap] ‘list’ disjoint ‘dups’?: true arrayList: [snap, snap, snap] *///:~ The output explains the behavior of each utility method. Note the difference in min( ) and max( ) with the String.CASE_INSENSITIVE_ORDER Comparator because of capitalization. Sorting and searching Lists Utilities to perform sorting and searching for Lists have the same names and signatures as those for sorting arrays of objects, but are static methods of Collections instead of Arrays. Here’s an example that uses the list data from Utilities.java: //: containers/ListSortSearch.java // Sorting and searching Lists with Collections utilities. import java.util.*; import static net.mindview.util.Print.*; public class ListSortSearch { public static void main(String[] args) { List<String> list = new ArrayList<String>(Utilities.list); list.addAll(Utilities.list); print(list); Collections.shuffle(list, new Random(47)); print("Shuffled: " + list); // Use a ListIterator to trim off the last elements: ListIterator<String> it = list.listIterator(10); while(it.hasNext()) { it.next(); it.remove(); } print("Trimmed: " + list); Collections.sort(list); print("Sorted: " + list); String key = list.get(7); int index = Collections.binarySearch(list, key); print("Location of " + key + " is " + index + ", list.get(" + index + ") = " + list.get(index)); Collections.sort(list, String.CASE_INSENSITIVE_ORDER); print("Case-insensitive sorted: " + list); key = list.get(7); index = Collections.binarySearch(list, key, String.CASE_INSENSITIVE_ORDER); print("Location of " + key + " is " + index + ", list.get(" + index + ") = " + list.get(index)); } Containers in Depth 635 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com  } /* Output: [one, Two, three, Four, five, six, one, one, Two, three, Four, five, six, one] Shuffled: [Four, five, one, one, Two, six, six, three, three, five, Four, Two, one, one] Trimmed: [Four, five, one, one, Two, six, six, three, three, five] Sorted: [Four, Two, five, five, one, one, six, six, three, three] Location of six is 7, list.get(7) = six Case-insensitive sorted: [five, five, Four, one, one, six, six, three, three, Two] Location of three is 7, list.get(7) = three *///:~ Just as when searching and sorting with arrays, if you sort using a Comparator, you must binarySearch( ) using the same Comparator. This program also demonstrates the shuffle( ) method in Collections, which randomizes the order of a List. A ListIterator is created at a particular location in the shuffled list, and used to remove the elements from that location until the end of the list. Exercise 40: (5) Create a class containing two String objects and make it Comparable so that the comparison only cares about the first String. Fill an array and an ArrayList with objects of your class, using the RandomGenerator generator. Demonstrate that sorting works properly. Now make a Comparator that only cares about the second String, and demonstrate that sorting works properly. Also perform a binary search using your Comparator. Exercise 41: (3) Modify the class in the previous exercise so that it will work with HashSets and as a key in HashMaps. Exercise 42: (2) Modify Exercise 40 so that an alphabetic sort is used. Making a Collection or Map unmodifiable Often it is convenient to create a read-only version of a Collection or Map. The Collections class allows you to do this by passing the original container into a method that hands back a read-only version. There are a number of variations on this method, for Collections (if you can’t treat a Collection as a more specific type), Lists, Sets, and Maps. This example shows the proper way to build read-only versions of each: //: containers/ReadOnly.java // Using the Collections.unmodifiable methods. import java.util.*; import net.mindview.util.*; import static net.mindview.util.Print.*; public class ReadOnly { static Collection<String> data = new ArrayList<String>(Countries.names(6)); public static void main(String[] args) { Collection<String> c = Collections.unmodifiableCollection( new ArrayList<String>(data)); print(c); // Reading is OK //! c.add("one"); // Can’t change it List<String> a = Collections.unmodifiableList( 636 Thinking in Java Bruce Eckel Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... StringBuilder(); for(int j = 0; j < b.size() ; j++) bbits.append(b.get(j) ? "1" : "0"); print("bit pattern: " + bbits); } 644 Thinking in Java Bruce Eckel   Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com public static void main(String[] args) { Random rand = new Random( 47) ; // Take the LSB of nextInt(): byte bt = (byte)rand.nextInt(); BitSet bb = new BitSet(); for(int i = 7; ... early Java libraries, these oddities were not accidents, but carefully considered decisions based on trade-offs in complexity Solutions to selected exercises can be found in the electronic document The Thinking in Java Annotated Solution Guide, available for sale from www.MindView.net   646 Thinking in Java Bruce Eckel   Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com I/O Creating... //: containers/References .java // Demonstrates Reference objects import java. lang.ref.*; import java. util.*; class VeryBig { private static final int SIZE = 10000; private long[] la = new long[SIZE]; private String ident; public VeryBig(String id) { ident = id; } public String toString() { return ident; } protected void finalize() { System.out.println("Finalizing " + ident); } } Containers in Depth... DirectoryDemo { public static void main(String[] args) { // All directories: PPrint.pprint(Directory.walk(".").dirs); // All files beginning with ‘T’ for(File file : Directory.local(".", "T.*")) print(file); print(" "); // All Java files beginning with ‘T’: for(File file : Directory.walk(".", "T.*\\ .java" )) print(file); print("======================"); // Class files containing "Z" or "z": for(File file... setLineNumber (int) InputStream Has a one-byte pushback buffer so that you can push back the last character read InputStream Contains a full interface to allow you to read primitive types This doesn’t provide an interface per se It just adds buffering to the process Attach an interface object This just adds line numbering, so you’ll probably attach an interface object Generally used in the 660 Thinking. .. // Treating a stack as a Vector: stack.addElement("The last line"); print("element 5 = " + stack.elementAt(5)); print("popping elements:"); while(!stack.empty()) printnb(stack.pop() + " "); // Using a LinkedList as a Stack: LinkedList lstack = new LinkedList(); for(Month m : Month.values()) lstack.addFirst(m.toString()); print("lstack = " + lstack); while(!lstack.isEmpty()) printnb(lstack.removeFirst()... (alphabetically) using the java. util.Arrays.sort( ) method and the String.CASE_INSENSITIVE_ORDER Comparator: //: io/DirList .java // Display a directory listing using regular expressions // {Args: "D.*\ .java" } import java. util.regex.*; import java. io.*;     Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com import java. util.*; public class DirList { public static void main(String[] args)... file Using accept( ), the list( ) method returns an array 648 Thinking in Java Bruce Eckel   Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Anonymous inner classes This example is ideal for rewriting using an anonymous inner class (described in Inner Classes) As a first cut, a method filter( ) is created that returns a reference to a FilenameFilter: //: io/DirList2 .java //... expression in either a local directory, // or by walking a directory tree package net.mindview.util; import java. util.regex.*; import java. io.*; import java. util.*; public final class Directory { public static File[] 650 Thinking in Java Bruce Eckel   Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com local(File dir, final String regex) { return dir.listFiles(new FilenameFilter()... Treelnfo.toString( ) method uses a "pretty printer" class so that the output is easer to view The default toString( ) methods for containers print all the elements for a container on a single line For large collections this can become difficult to read, so you may want to use an alternate formatting Here’s a tool that adds newlines and indents each element: //: net/mindview/util/PPrint .java // Pretty-printer . http://www.simpopdf.com  10 74 8 168 100 100 506 264 76 1000 77 1 450 78 10000 2962 561 83 HashMap size put get iterate 10 281 76 93 100 179 70 73 1000 2 67 102 72 10000 1305 265 97 LinkedHashMap. 10000 1 975 552 69 HashSet size add contains iterate 10 308 91 94 100 178 75 73 1000 216 110 72 10000 71 1 215 100 LinkedHashSet size add contains iterate 10 350 65 83 100 270 74 . for insertions because it maintains the linked list (to preserve insertion order) in addition to the hashed data structure. Because of this list, iteration is faster. 630 Thinking in Java

Ngày đăng: 14/08/2014, 00:21

Từ khóa liên quan

Mục lục

  • Thinking in Java

  • Content

Tài liệu cùng người dùng

Tài liệu liên quan