一、接口
- Collection:构建集合框架的基础,定义集合的所有类都必须实现该接口。
- List:线性表,Collection接口扩展。
- Set:集,Collection接口扩展。
- SorttedSet:以升序排序的集,Set接口扩展。
- NavigableSet:可基于最接近匹配原则检索元素的集,SortedSet接口扩展。
- Queue:队列,Collection接口扩展。
- Deque:双端队列,Queue接口扩展。
二、集合类
动态数组。
import java.util.ArrayList; class Solution { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(100);//初始大小100 for (int i = 0; i < 100; i++) list.add(i); list.ensureCapacity(500);//重置大小为500 for (int i = 100; i < 500; i++) list.add(i); Integer[] arr = new Integer[list.size()]; arr = list.toArray(arr);//获取数组 for (int i : arr) System.out.println(i); } }
链表。
import java.util.LinkedList; class Solution { public static void main(String[] args) { LinkedList<Integer> list = new LinkedList<>(); for (int i = 0; i < 100; i++) list.add(i);//插入尾元素 for (int i = 100; i < 200; i++) list.push(i);//插入首元素 list.removeFirst();//删除首元素 list.removeLast();//删除尾元素 System.out.println(list); } }
哈希集。
import java.util.HashSet; class Solution { public static void main(String[] args) { HashSet<Integer> setA = new HashSet<>();//默认容量16 HashSet<Integer> setB = new HashSet<>(100, (float) 0.8);//初始容量为100,填充率到达0.8时扩容 } }
三、迭代器
迭代器是实现了Iterator接口或ListIterator接口的对象。ListIterator接口为Iterator接口的扩展,支持双向遍历。
import java.util.ArrayList; import java.util.Iterator; class Solution { public static void main(String[] args) { ArrayList<Character> list = new ArrayList<>(); for (char c = ‘A‘; c <= ‘E‘; c++) list.add(c); //迭代器遍历 Iterator<Character> itr = list.iterator(); while (itr.hasNext()) System.out.print(itr.next()); //foreach遍历 for (char c : list) System.out.print(c); } }
实现了Spliterator的迭代器可循环遍历,并且支持并行迭代。它将hasNext和next合并以提高效率。
import java.util.ArrayList; import java.util.Spliterator; class Solution { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < 10; i++) list.add(i); Spliterator<Integer> splitr = list.spliterator(); while (splitr.tryAdvance((i) -> System.out.println(i))); splitr = list.spliterator(); splitr.forEachRemaining((i) -> System.out.println(i)); } }
四、映射
- Map:将键映射到值。
- Map.Entry:描述键值对。
- SortedMap:以升序保存键,Map接口扩展。
- NavigableMap:基于最接近匹配的键值对检索,SortedMap接口扩展。
哈希映射,无序。
import java.util.HashMap; class Solution { public static void main(String[] args) { HashMap<String, Integer> months = new HashMap<>(); months.put("Jan", 1); months.put("Feb", 2); months.put("Mar", 3); months.put("Apr", 4); months.put("May", 5); months.put("June", 6); months.put("July", 7); months.put("Aug", 8); months.put("Sept", 9); months.put("Oct", 10); months.put("Nov", 11); months.put("Dec", 12); System.out.println(months.entrySet()); System.out.println(months.keySet());//[June, Sept, Oct, Feb, Apr, Aug, Dec, May, Nov, Jan, July, Mar] System.out.println(months.values());//[6, 9, 10, 2, 4, 8, 12, 5, 11, 1, 7, 3] } }
红黑树映射,有序。
import java.util.TreeMap; class Solution { public static void main(String[] args) { TreeMap<String, Integer> months = new TreeMap<>(); months.put("Jan", 1); months.put("Feb", 2); months.put("Mar", 3); months.put("Apr", 4); months.put("May", 5); months.put("June", 6); months.put("July", 7); months.put("Aug", 8); months.put("Sept", 9); months.put("Oct", 10); months.put("Nov", 11); months.put("Dec", 12); System.out.println(months.entrySet()); System.out.println(months.keySet());//[Apr, Aug, Dec, Feb, Jan, July, June, Mar, May, Nov, Oct, Sept] System.out.println(months.values());//[4, 8, 12, 2, 1, 7, 6, 3, 5, 11, 10, 9] } }
哈希映射链表实现,按插入顺序迭代。
import java.util.LinkedHashMap; class Solution { public static void main(String[] args) { LinkedHashMap<String, Integer> months = new LinkedHashMap<>(); months.put("Jan", 1); months.put("Feb", 2); months.put("Mar", 3); months.put("Apr", 4); months.put("May", 5); months.put("June", 6); months.put("July", 7); months.put("Aug", 8); months.put("Sept", 9); months.put("Oct", 10); months.put("Nov", 11); months.put("Dec", 12); System.out.println(months.entrySet()); System.out.println(months.keySet());//[Jan, Feb, Mar, Apr, May, June, July, Aug, Sept, Oct, Nov, Dec] System.out.println(months.values());//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] } }
五、比较器
如果希望以不同的方式排序元素,可以再构造集合时指定比较器。
Comparator是泛型接口,部分方法如下
- compare:比较对象的大小。
- equals:测试比较器的排序顺序是否相同。
- reversed:获取相反顺序的比较器。
- reverseOrder:获取相反元素的自然顺序比较器。
- naturalOrder:获取自然顺序比较器。
- nullsFirst:认为null比其他值小的比较器。
- nullsLast:认为null比其他值大的比较器。
- thenComparing:当首次比较相等时指定其他比较器。
import java.util.Comparator; import java.util.TreeSet; class Student { String name; int total; Student(String name, int total) { this.name = name; this.total = total; } @Override public String toString() { return name + " " + total; } } class StudentComparator implements Comparator<Student> { @Override public int compare(Student a, Student b) { if (a.total != b.total) return a.total - b.total; else return a.name.compareTo(b.name); } } class Solution { public static void main(String[] args) { TreeSet<Student> set = new TreeSet<>(new StudentComparator().reversed()); StringBuilder nameBuilder = new StringBuilder(); for (int i = 0; i < 1000; i++) { int total = (int) (750 * Math.random()); for (int j = 0; j < 3; j++) nameBuilder.append((char) (25 * Math.random() + 65)); set.add(new Student(nameBuilder.toString(), total)); nameBuilder.delete(0, nameBuilder.length()); } System.out.println(set); } }
函数式接口。
Comparator<Student> comp = (a, b) -> { if (a.total != b.total) return a.total - b.total; else return a.name.compareTo(b.name); }; TreeSet<Student> set = new TreeSet<>(comp);
thenComparing。
import java.util.Comparator; import java.util.TreeSet; class Student { String name; int total; Student(String name, int total) { this.name = name; this.total = total; } @Override public String toString() { return name + " " + total; } } class ComparatorA implements Comparator<Student> { @Override public int compare(Student a, Student b) { return a.total - b.total; } } class ComparatorB implements Comparator<Student> { @Override public int compare(Student a, Student b) { return a.name.compareTo(b.name); } } class Solution { public static void main(String[] args) { ComparatorA compA = new ComparatorA(); Comparator<Student> comp = compA.thenComparing(new ComparatorB()); TreeSet<Student> set = new TreeSet<>(comp); StringBuilder nameBuilder = new StringBuilder(); for (int i = 0; i < 1000; i++) { int total = (int) (750 * Math.random()); for (int j = 0; j < 3; j++) nameBuilder.append((char) (25 * Math.random() + 65)); set.add(new Student(nameBuilder.toString(), total)); nameBuilder.delete(0, nameBuilder.length()); } System.out.println(set); } }
六、集合算法
集合框架定义了可用于集合和映射的算法,这些算法被定义为Collections中的静态方法。
import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; class Solution { public static void main(String[] args) { LinkedList<Integer> list = new LinkedList<>(); for (int i = 0; i < 10; i++) list.add(i); Comparator<Integer> comp = Collections.reverseOrder();//获取整数的反向比较器 Collections.sort(list, comp); System.out.println(list);//[9, 8, 7, 6, 5, 4, 3, 2, 1, 0] System.out.println(Collections.max(list)); System.out.println(Collections.min(list)); Collections.shuffle(list);//随机化 System.out.println(list); } }
数组算法。
import java.util.Arrays; import java.util.Collections; import java.util.Spliterator; import java.util.stream.Stream; class Solution { public static void main(String[] args) { Integer[] arr = {1, 2, 3, 4, 5}; System.out.println(Arrays.binarySearch(arr, 0));//-1 Integer[] cpyA = Arrays.copyOf(arr, 3);//1 2 3 Integer[] cpyB = Arrays.copyOfRange(arr, 0, 3);//1 2 3 System.out.println(Arrays.equals(cpyA, cpyB)); Arrays.sort(arr, Collections.reverseOrder()); Arrays.parallelSort(arr);//并行排序 Spliterator<Integer> splitr = Arrays.spliterator(arr);//获取迭代器 Stream<Integer> stream = Arrays.stream(arr);//获取流 } }
七、遗留类与接口
Vector实现了动态数组。ArrayList与其的主要区别是Vector是同步的,并且包含许多遗留方法。
import java.util.Collections; import java.util.Vector; class Solution { public static void main(String[] args) { Vector<Integer> vector = new Vector<>(); for (int i = 0; i < 100; i++) vector.addElement(i); vector.sort(Collections.reverseOrder()); for (int i = 0; i < vector.size(); i++) System.out.println(vector.elementAt(i)); } }
Stack是Vector的子类,实现了标准的堆栈。不反对使用,但ArrayDeque是更好的选择。
import java.util.Stack; class Solution { public static void main(String[] args) { Stack<Integer> stack = new Stack<>(); for (int i = 0; i < 100; i++) stack.push(i); while (!stack.empty()) System.out.println(stack.pop()); } }
Dictionary是表示键值对存储库的抽象类。已被Map完全取代,不推荐使用。
Hashtable原本是Dictionary的具体实现,随着集合的出现Hashtable被重新设计并实现了Map接口。Hashtable与HashMap的主要区别是Hashtable是线程安全的,两者的底层均是数组+链表实现,填充率均为0.75,但Hashtable不直接支持迭代器。
import java.util.Hashtable; import java.util.Iterator; import java.util.Set; class Solution { public static void main(String[] args) { Hashtable<String, Integer> table = new Hashtable<>(); table.put("A", 1); table.put("C", 2); table.put("B", 4); table.put("E", 3); table.put("D", 5); Set<String> set = table.keySet(); Iterator<String> itr = table.keySet().iterator(); while (itr.hasNext()) System.out.println(itr.next()); } }
Properties是Hashtable的子类,用于保存值的列表。Properties可以指定默认属性。如果没有值与特定键关联,就会返回默认属性。
import java.util.Properties; class Solution { public static void main(String[] args) { Properties p = new Properties(); p.put("A", "1"); p.put("B", "2"); p.put("C", "3"); System.out.println(p.getProperty("E", "-1"));//-1 } }
使用store方法和load方法可以将Properties存储到磁盘以及从磁盘中加载。
import java.io.*; import java.util.Properties; class Solution { public static void main(String[] args) throws IOException { Properties information = new Properties(); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String name, number; FileInputStream fin = null; try { fin = new FileInputStream("file.txt"); } catch (FileNotFoundException exc) { System.out.println("File not found"); } try { if (fin != null) { information.load(fin);//载入信息 fin.close(); } } catch (IOException exc) { System.out.println("Error reading file"); } name = reader.readLine(); number = reader.readLine(); information.put(name, number); FileOutputStream fout = new FileOutputStream("file.txt"); information.store(fout, "Information");//存储信息 fout.close(); } }