以下是各程序清单的执行结果及核心要点解析Listing 1: ArrayListDemoimport java.util.*; class ArrayListDemo { public static void main(String args[]) { ArrayListString al new ArrayListString(); System.out.println(Initial size of al: al.size()); al.add(C); al.add(A); al.add(E); al.add(B); al.add(D); al.add(F); al.add(1, A2); System.out.println(Size of al after additions: al.size()); System.out.println(Contents of al: al); al.remove(F); al.remove(2); System.out.println(Size of al after deletions: al.size()); System.out.println(Contents of al: al); } }执行结果Initial size of al: 0 Size of al after additions: 7 Contents of al: [C, A2, A, E, B, D, F] Size of al after deletions: 5 Contents of al: [C, A2, E, B, D]解析演示了ArrayList的基本操作创建、获取大小、添加元素包括在指定索引处插入、删除元素按对象和按索引以及打印内容。al.add(1, A2)在索引1处插入元素后续元素后移。al.remove(F)删除第一个匹配的F元素。al.remove(2)删除索引为2的元素此时是A。Listing 2: ArrayListToArrayimport java.util.*; class ArrayListToArray { public static void main(String args[]) { ArrayListInteger al new ArrayListInteger(); al.add(1); al.add(2); al.add(3); al.add(4); System.out.println(Contents of al: al); Integer ia[] new Integer[al.size()]; ia al.toArray(ia); int sum 0; for(int i : ia) sum i; System.out.println(Sum is: sum); } }执行结果Contents of al: [1, 2, 3, 4] Sum is: 10解析演示了如何将ArrayList转换为数组。al.toArray(ia)方法将列表元素复制到提供的数组ia中并返回该数组。Listing 3: LinkedListDemoimport java.util.*; class LinkedListDemo { public static void main(String args[]) { LinkedListString ll new LinkedListString(); ll.add(F); ll.add(B); ll.add(D); ll.add(E); ll.add(C); ll.addLast(Z); ll.addFirst(A); ll.add(1, A2); System.out.println(Original contents of ll: ll); ll.remove(F); ll.remove(2); System.out.println(Contents of ll after deletion: ll); ll.removeFirst(); ll.removeLast(); System.out.println(ll after deleting first and last: ll); String val ll.get(2); ll.set(2, val Changed); System.out.println(ll after change: ll); } }执行结果Original contents of ll: [A, A2, F, B, D, E, C, Z] Contents of ll after deletion: [A, A2, D, E, C, Z] ll after deleting first and last: [A2, D, E, C] ll after change: [A2, D, E Changed, C]解析演示了LinkedList作为双向链表的特有操作addFirst()、addLast()、removeFirst()、removeLast()。也支持类似ArrayList的索引操作get、set但效率较低。Listing 4: HashSetDemoimport java.util.*; class HashSetDemo { public static void main(String args[]) { HashSetString hs new HashSetString(); hs.add(Beta); hs.add(Alpha); hs.add(Eta); hs.add(Gamma); hs.add(Epsilon); hs.add(Omega); System.out.println(hs); } }执行结果示例顺序不保证[Gamma, Alpha, Epsilon, Omega, Beta, Eta]解析HashSet是基于哈希表实现的集合不保证元素的顺序既不是插入顺序也不是排序顺序。它不允许重复元素。Listing 5: TreeSetDemoimport java.util.*; class TreeSetDemo { public static void main(String args[]) { TreeSetString ts new TreeSetString(); ts.add(C); ts.add(A); ts.add(B); ts.add(E); ts.add(F); ts.add(D); System.out.println(ts); } }执行结果[A, B, C, D, E, F]解析TreeSet是基于红黑树一种自平衡二叉查找树实现的集合元素会按照自然顺序或指定的Comparator自动排序。Listing 6: ArrayDequeDemoimport java.util.*; class ArrayDequeDemo { public static void main(String args[]) { ArrayDequeString adq new ArrayDequeString(); adq.push(A); adq.push(B); adq.push(D); adq.push(E); adq.push(F); System.out.print(Popping the stack: ); while(adq.peek() ! null) System.out.print(adq.pop() ); System.out.println(); } }执行结果Popping the stack: F E D B A解析ArrayDeque是一个基于数组的双端队列。这里使用push()和pop()方法将其作为栈后进先出LIFO使用。push(E e)等效于addFirst(e)pop()等效于removeFirst()。Listing 7: IteratorDemoimport java.util.*; class IteratorDemo { public static void main(String args[]) { ArrayListString al new ArrayListString(); al.add(C); al.add(A); al.add(E); al.add(B); al.add(D); al.add(F); System.out.print(Original contents of al: ); IteratorString itr al.iterator(); while(itr.hasNext()) { String element itr.next(); System.out.print(element ); } System.out.println(); ListIteratorString litr al.listIterator(); while(litr.hasNext()) { String element litr.next(); litr.set(element ); } System.out.print(Modified contents of al: ); itr al.iterator(); while(itr.hasNext()) { String element itr.next(); System.out.print(element ); } System.out.println(); System.out.print(Modified list backwards: ); while(litr.hasPrevious()) { String element litr.previous(); System.out.print(element ); } System.out.println(); } }执行结果Original contents of al: C A E B D F Modified contents of al: C A E B D F Modified list backwards: F D B E A C解析演示了Iterator和ListIterator的用法。Iterator用于单向遍历集合。ListIterator是Iterator的增强版支持双向遍历hasPrevious(),previous()和在遍历过程中修改元素set()。Listing 8: ForEachDemoimport java.util.*; class ForEachDemo { public static void main(String args[]) { ArrayListInteger vals new ArrayListInteger(); vals.add(1); vals.add(2); vals.add(3); vals.add(4); vals.add(5); System.out.print(Original contents of vals: ); for(int v : vals) System.out.print(v ); System.out.println(); int sum 0; for(int v : vals) sum v; System.out.println(Sum of values: sum); } }执行结果Original contents of vals: 1 2 3 4 5 Sum of values: 15解析演示了增强型 for 循环for-each 循环遍历集合。语法简洁无需显式使用迭代器。Listing 9: SpliteratorDemoimport java.util.*; class SpliteratorDemo { public static void main(String args[]) { ArrayListDouble vals new ArrayList(); vals.add(1.0); vals.add(2.0); vals.add(3.0); vals.add(4.0); vals.add(5.0); System.out.print(Contents of vals: ); SpliteratorDouble spltitr vals.spliterator(); while(spltitr.tryAdvance((n) - System.out.println(n))); System.out.println(); spltitr vals.spliterator(); ArrayListDouble sqrs new ArrayList(); while(spltitr.tryAdvance((n) - sqrs.add(Math.sqrt(n)))); System.out.print(Contents of sqrs: ); spltitr sqrs.spliterator(); spltitr.forEachRemaining((n) - System.out.println(n)); System.out.println(); } }执行结果Contents of vals: 1.0 2.0 3.0 4.0 5.0Contents of sqrs: 1.0 1.4142135623730951 1.7320508075688772 2.02.23606797749979解析演示了 Java 8 引入的Spliterator可分割迭代器用于遍历和分割源元素特别适合并行处理。tryAdvance()逐个消费元素forEachRemaining()消费剩余所有元素。Listing 10: MailListimport java.util.*; class Address { private String name; private String street; private String city; private String state; private String code; Address(String n, String s, String c, String st, String cd) { name n; street s; city c; state st; code cd; } public String toString() { return name street city state code; } } class MailList { public static void main(String args[]) { LinkedListAddress ml new LinkedListAddress(); ml.add(new Address(J.W. West, 11 Oak Ave, Urbana, IL, 61801)); ml.add(new Address(Ralph Baker, 1142 Maple Lane, Mahome, IL, 61853)); ml.add(new Address(Tom Carlton, 867 Elm St, Champaign, IL, 61820)); for(Address element : ml) System.out.println(element ); System.out.println(); } }执行结果J.W. West 11 Oak Ave Urbana IL 61801 Ralph Baker 1142 Maple Lane Mahome IL 61853 Tom Carlton 867 Elm St Champaign IL 61820解析展示了在集合LinkedList中存储自定义对象Address。通过重写toString()方法可以方便地打印对象内容。Listing 11: HashMapDemoimport java.util.*; class HashMapDemo { public static void main(String args[]) { HashMapString, Double hm new HashMapString, Double(); hm.put(John Doe, 3434.34); hm.put(Tom Smith, 123.22); hm.put(Jane Baker, 1378.00); hm.put(Tod Hall, 99.22); hm.put(Ralph Smith, -19.08); SetMap.EntryString, Double set hm.entrySet(); for(Map.EntryString, Double me : set) { System.out.print(me.getKey() : ); System.out.println(me.getValue()); } System.out.println(); double balance hm.get(John Doe); hm.put(John Doe, balance 1000); System.out.println(John Does new balance: hm.get(John Doe)); } }执行结果示例顺序不保证Ralph Smith: -19.08 Tom Smith: 123.22 John Doe: 3434.34 Tod Hall: 99.22 Jane Baker: 1378.0 John Does new balance: 4434.34解析演示了HashMap的基本操作put()添加键值对get()根据键获取值entrySet()获取包含所有映射的集合视图用于遍历。HashMap不保证映射的顺序。Listing 12: TreeMapDemoimport java.util.*; class TreeMapDemo { public static void main(String args[]) { TreeMapString, Double tm new TreeMapString, Double(); tm.put(John Doe, 3434.34); tm.put(Tom Smith, 123.22); tm.put(Jane Baker, 1378.00); tm.put(Tod Hall, 99.22); tm.put(Ralph Smith, -19.08); SetMap.EntryString, Double set tm.entrySet(); for(Map.EntryString, Double me : set) { System.out.print(me.getKey() : ); System.out.println(me.getValue()); } System.out.println(); double balance tm.get(John Doe); tm.put(John Doe, balance 1000); System.out.println(John Does new balance: tm.get(John Doe)); } }执行结果Jane Baker: 1378.0 John Doe: 3434.34 Ralph Smith: -19.08 Tod Hall: 99.22 Tom Smith: 123.22John Does new balance: 4434.34解析TreeMap是基于红黑树实现的Map会根据键的自然顺序或指定的比较器对键进行排序。输出顺序是按键姓名的字典序排列的。Listing 13: CompDemo (自定义比较器)import java.util.*; class MyComp implements ComparatorString { public int compare(String aStr, String bStr) { return bStr.compareTo(aStr); // 反向比较 } } class CompDemo { public static void main(String args[]) { TreeSetString ts new TreeSetString(new MyComp()); ts.add(C); ts.add(A); ts.add(B); ts.add(E); ts.add(F); ts.add(D); for(String element : ts) System.out.print(element ); System.out.println(); } }执行结果F E D C B A解析通过实现Comparator接口并重写compare方法可以自定义TreeSet的排序规则。此处实现了降序排序。Listing 14: CompDemo2 (Lambda表达式比较器)import java.util.*; class CompDemo2 { public static void main(String args[]) { TreeSetString ts new TreeSetString((aStr, bStr) - bStr.compareTo(aStr)); ts.add(C); ts.add(A); ts.add(B); ts.add(E); ts.add(F); ts.add(D); for(String element : ts) System.out.print(element ); System.out.println(); } }执行结果F E D C B A解析使用 Lambda 表达式简化了自定义比较器的创建功能与 Listing 13 相同代码更简洁。Listing 15: TreeMapDemo2 (按姓氏排序)import java.util.*; class TComp implements ComparatorString { public int compare(String aStr, String bStr) { int i, j, k; i aStr.lastIndexOf( ); j bStr.lastIndexOf( ); k aStr.substring(i).compareToIgnoreCase(bStr.substring(j)); if(k0) return aStr.compareToIgnoreCase(bStr); else return k; } } class TreeMapDemo2 { public static void main(String args[]) { TreeMapString, Double tm new TreeMapString, Double(new TComp()); tm.put(John Doe, 3434.34); tm.put(Tom Smith, 123.22); tm.put(Jane Baker, 1378.00); tm.put(Tod Hall, 99.22); tm.put(Ralph Smith, -19.08); SetMap.EntryString, Double set tm.entrySet(); for(Map.EntryString, Double me : set) { System.out.print(me.getKey() : ); System.out.println(me.getValue()); } System.out.println(); double balance tm.get(John Doe); tm.put(John Doe, balance 1000); System.out.println(John Does new balance: tm.get(John Doe)); } }执行结果Jane Baker: 1378.0 John Doe: 3434.34 Tod Hall: 99.22 Ralph Smith: -19.08 Tom Smith: 123.22 John Does new balance: 4434.34解析自定义比较器TComp首先比较键字符串的姓氏最后一个空格后的部分如果姓氏相同则比较全名。因此“Ralph Smith” 排在 “Tom Smith” 之前。Listing 16: TreeMapDemo2A (使用 thenComparing)import java.util.*; class CompLastNames implements ComparatorString { public int compare(String aStr, String bStr) { int i aStr.lastIndexOf( ); int j bStr.lastIndexOf( ); return aStr.substring(i).compareToIgnoreCase(bStr.substring(j)); } } class CompThenByFirstName implements ComparatorString { public int compare(String aStr, String bStr) { return aStr.compareToIgnoreCase(bStr); } } class TreeMapDemo2A { public static void main(String args[]) { CompLastNames compLN new CompLastNames(); ComparatorString compLastThenFirst compLN.thenComparing(new CompThenByFirstName()); TreeMapString, Double tm new TreeMapString, Double(compLastThenFirst); tm.put(John Doe, 3434.34); tm.put(Tom Smith, 123.22); tm.put(Jane Baker, 1378.00); tm.put(Tod Hall, 99.22); tm.put(Ralph Smith, -19.08); SetMap.EntryString, Double set tm.entrySet(); for(Map.EntryString, Double me : set) { System.out.print(me.getKey() : ); System.out.println(me.getValue()); } System.out.println(); double balance tm.get(John Doe); tm.put(John Doe, balance 1000); System.out.println(John Does new balance: tm.get(John Doe)); } }执行结果Jane Baker: 1378.0 John Doe: 3434.34 Tod Hall: 99.22 Ralph Smith: -19.08 Tom Smith: 123.22 John Does new balance: 4434.34解析使用Comparator.thenComparing()方法组合多个比较器。先按姓氏比较CompLastNames如果姓氏相同再按全名比较CompThenByFirstName。结果与 Listing 15 相同但实现方式更模块化。Listing 17: AlgorithmsDemoimport java.util.*; class AlgorithmsDemo { public static void main(String args[]) { LinkedListInteger ll new LinkedListInteger(); ll.add(-8); ll.add(20); ll.add(-20); ll.add(8); ComparatorInteger r Collections.reverseOrder(); Collections.sort(ll, r); System.out.print(List sorted in reverse: ); for(int i : ll) System.out.print(i ); System.out.println(); Collections.shuffle(ll); System.out.print(List shuffled: ); for(int i : ll) System.out.print(i ); System.out.println(); System.out.println(Minimum: Collections.min(ll)); System.out.println(Maximum: Collections.max(ll)); } }执行结果示例shuffle 结果随机List sorted in reverse: 20 88 -20 List shuffled: 8 -20 20 -8 Minimum: -20 Maximum: 20解析演示了Collections工具类的常用算法sort()排序可传入反向比较器、shuffle()随机打乱、min()求最小值、max()求最大值。Listing 18: ArraysDemoimport java.util.*; class ArraysDemo { static void display(int array[]) { for(int i: array) System.out.print(i ); System.out.println(); } public static void main(String args[]) { int array[] new int[10]; for(int i 0; i 10; i) array[i] -3 * i; System.out.print(Original contents: ); display(array); Arrays.sort(array); System.out.print(Sorted: ); display(array); Arrays.fill(array, 2, 6, -1); System.out.print(After fill(): ); display(array); Arrays.sort(array); System.out.print(After sorting again: ); display(array); System.out.print(The value -9 is at location ); int index Arrays.binarySearch(array, -9); System.out.println(index); } }执行结果Original contents: 0 -3 -6 -9 -12 -15 -18 -21 -24 -27 Sorted: -27 -24 -21 -18 -15 -12 -9 -63 0 After fill(): -27 -24 -1 -1 -1 -1 -9 -6 -3 0 After sorting again: -27 -24 -9 -6 -3 -1 -1 -1 -1 0The value -9 is at location 2解析演示了Arrays工具类的常用方法sort()排序、fill()填充指定范围的元素、binarySearch()在已排序数组中进行二分查找。Listing 19: VectorDemoimport java.util.*; class VectorDemo { public static void main(String args[]) { VectorInteger v new VectorInteger(3, 2); System.out.println(Initial size: v.size()); System.out.println(Initial capacity: v.capacity()); v.addElement(1); v.addElement(2); v.addElement(3); v.addElement(4); System.out.println(Capacity after four additions: v.capacity()); v.addElement(5); System.out.println(Current capacity: v.capacity()); v.addElement(6); v.addElement(7); System.out.println(Current capacity: v.capacity()); v.addElement(9); v.addElement(10); System.out.println(Current capacity: v.capacity()); v.addElement(11); v.addElement(12); System.out.println(First element: v.firstElement()); System.out.println(Last element: v.lastElement()); if(v.contains(3)) System.out.println(Vector contains 3.); EnumerationInteger vEnum v.elements(); System.out.println( Elements in vector:); while(vEnum.hasMoreElements()) System.out.print(vEnum.nextElement() ); System.out.println(); } }执行结果Initial size: 0 Initial capacity: 3 Capacity after four additions: 5 Current capacity: 5 Current capacity: 7 Current capacity: 9 First element: 1 Last element: 12 Vector contains 3. Elements in vector: 1 2 3 4 5 6 7 9 10 11 12解析Vector是一个线程安全的、可动态增长的对象数组。构造时指定初始容量3和容量增量2。当添加元素超过当前容量时容量按增量2增加。使用传统的Enumeration接口进行遍历。Listing 20 21: Vector 的迭代器和 for-each 遍历代码接 Listing 19 的v// Listing 20: 使用迭代器 IteratorInteger vItr v.iterator(); System.out.println( Elements in vector:); while(vItr.hasNext()) System.out.print(vItr.next() ); System.out.println(); // Listing 21: 使用增强 for 循环 System.out.println( Elements in vector:); for(int i : v) System.out.print(i ); System.out.println();执行结果接上Elements in vector: 1 2 3 4 5 6 7 9 10 11 12 Elements in vector: 1 2 3 4 5 6 7 9 10 11 12解析展示了Vector的另外两种遍历方式Iterator和增强 for 循环与ArrayList用法一致。Listing 22: StackDemoimport java.util.*; class StackDemo { static void showpush(StackInteger st, int a) { st.push(a); System.out.println(push( a )); System.out.println(stack: st); } static void showpop(StackInteger st) { System.out.print(pop - ); Integer a st.pop(); System.out.println(a); System.out.println(stack: st); } public static void main(String args[]) { StackInteger st new StackInteger(); System.out.println(stack: st); showpush(st, 42); showpush(st, 66); showpush(st, 99); showpop(st); showpop(st); showpop(st); try { showpop(st); } catch (EmptyStackException e) { System.out.println(empty stack); } } }执行结果stack: [] push(42) stack: [42] push(66) stack: [42, 66] push(99) stack: [42, 66, 99] pop - 99 stack: [42, 66] pop - 66 stack: [42] pop - 42 stack: [] pop - empty stack解析演示了Stack栈后进先出 LIFO的基本操作push()入栈、pop()出栈。空栈调用pop()会抛出EmptyStackException。Listing 23: HTDemo (Hashtable)import java.util.*; class HTDemo { public static void main(String args[]) { HashtableString, Double balance new HashtableString, Double(); EnumerationString names; String str; double bal; balance.put(John Doe, 3434.34); balance.put(Tom Smith, 123.22); balance.put(Jane Baker, 1378.00); balance.put(Tod Hall, 99.22); balance.put(Ralph Smith, -19.08); names balance.keys(); while(names.hasMoreElements()) { str names.nextElement(); System.out.println(str : balance.get(str)); } System.out.println(); bal balance.get(John Doe); balance.put(John Doe, bal1000); System.out.println(John Does new balance: balance.get(John Doe)); } }执行结果示例顺序不保证Tod Hall: 99.22 John Doe: 3434.34 Tom Smith: 123.22 Ralph Smith: -19.08 Jane Baker: 1378.0 John Does new balance: 4434.34解析Hashtable是一个线程安全的、基于哈希表的Map实现。它不允许null键或值。使用传统的Enumeration遍历键集keys()。Listing 24: HTDemo2 (Hashtable with Iterator)import java.util.*; class HTDemo2 { public static void main(String args[]) { HashtableString, Double balance new HashtableString, Double(); String str; double bal; balance.put(John Doe, 3434.34); balance.put(Tom Smith, 123.22); balance.put(Jane Baker, 1378.00); balance.put(Tod Hall, 99.22); balance.put(Ralph Smith, -19.08); SetString set balance.keySet(); IteratorString itr set.iterator(); while(itr.hasNext()) { str itr.next(); System.out.println(str : balance.get(str)); } System.out.println(); bal balance.get(John Doe); balance.put(John Doe, bal1000); System.out.println(John Does new balance: balance.get(John Doe)); } }执行结果示例顺序不保证Tod Hall: 99.22 John Doe: 3434.34 Tom Smith: 123.22 Ralph Smith: -19.08 Jane Baker: 1378.0 John Does new balance: 4434.34解析功能与 Listing 23 相同但使用keySet()获取键的Set视图再通过Iterator进行遍历这是更现代的集合遍历方式。Listing 25: PropDemo (Properties)import java.util.*; class PropDemo { public static void main(String args[]) { Properties capitals new Properties(); capitals.put(Illinois, Springfield); capitals.put(Missouri, Jefferson City); capitals.put(Washington, Olympia); capitals.put(California, Sacramento); capitals.put(Indiana, Indianapolis); Set? states capitals.keySet(); for(Object name : states) System.out.println(The capital of name is capitals.getProperty((String)name) .); System.out.println(); String str capitals.getProperty(Florida, Not Found); System.out.println(The capital of Florida is str .); } }执行结果示例顺序不保证The capital of Missouri is Jefferson City. The capital of Illinois is Springfield. The capital of Indiana is Indianapolis. The capital of California is Sacramento. The capital of Washington is Olympia. The capital of Florida is Not Found.解析Properties是Hashtable的子类用于管理属性列表键值均为字符串。getProperty(key, defaultValue)方法在键不存在时返回默认值。Listing 26: PropDemoDef (带默认值的 Properties)import java.util.*; class PropDemoDef { public static void main(String args[]) { Properties defList new Properties(); defList.put(Florida, Tallahassee); defList.put(Wisconsin, Madison); Properties capitals new Properties(defList); capitals.put(Illinois, Springfield); capitals.put(Missouri, Jefferson City); capitals.put(Washington, Olympia); capitals.put(California, Sacramento); capitals.put(Indiana, Indianapolis); Set? states capitals.keySet(); for(Object name : states) System.out.println(The capital of name is capitals.getProperty((String)name) .); System.out.println(); String str capitals.getProperty(Florida); System.out.println(The capital of Florida is str .); } }执行结果示例顺序不保证The capital of Missouri is Jefferson City. The capital of Illinois is Springfield. The capital of Indiana is Indianapolis. The capital of California is Sacramento. The capital of Washington is Olympia. The capital of Florida is Tallahassee.解析创建Properties时可以指定一个默认属性列表。当在主列表中找不到某个键时会到默认列表中查找。Listing 27: Phonebook (Properties 文件存储)/* A simple telephone number database that uses a property list. */ import java.io.*; import java.util.*; class Phonebook { public static void main(String args[]) throws IOException { Properties ht new Properties(); BufferedReader br new BufferedReader(new InputStreamReader(System.in)); String name, number; FileInputStream fin null; boolean changed false; try { fin new FileInputStream(phonebook.dat); } catch(FileNotFoundException e) { } try { if(fin ! null) { ht.load(fin); fin.close(); } } catch(IOException e) { System.out.println(Error reading file.); } do { System.out.println(Enter new name (quit to stop): ); name br.readLine(); if(name.equals(quit)) continue; System.out.println(Enter number: ); number br.readLine(); ht.put(name, number); changed true; } while(!name.equals(quit)); if(changed) { FileOutputStream fout new FileOutputStream(phonebook.dat); ht.store(fout, Telephone Book); fout.close(); } do { System.out.println(Enter name to find (quit to quit): ); name br.readLine(); if(name.equals(quit)) continue; number (String) ht.get(name); System.out.println(number); } while(!name.equals(quit)); } }执行结果交互式程序示例Enter new name (quit to stop): Alice Enter number: 123456 Enter new name (quit to stop): Bob Enter number: 789012 Enter new name (quit to stop): quit Enter name to find (quit to quit): Alice 123456 Enter name to find (quit to quit): quit解析这是一个完整的电话簿程序使用Properties存储数据。ht.load(fin)从文件输入流加载属性列表。ht.store(fout, Telephone Book)将属性列表存储到文件输出流并附带注释。程序实现了数据的持久化存储和读取。参考来源【Java】集合框架集合类工具类【Java 集合框架】最全的 Java 集合框架入门手册深入解析Java集合框架分类、实现原理与代码示例Java笔记——Java集合框架_java 集合框架Java集合框架