u03-容器进阶

212 阅读7分钟

1. Collection接口

概念: java.util.Collection 继承自 java.lang.Iterable,表示java的容器类,方便我们更灵活地组织和操纵数据,它有三个常用的子接口:ListQueueSet

2. List接口

概念: List接口是相对有序(输入和输出相同)的一种容器,也称为序列,此接口的用户可以对列表中每个元素的插入位置进行精确地控制,用户可以根据元素的整数索引(在列表中的位置)来访问元素,并搜索列表中的元素。

2.1 ArrayList实现类

概念: ArrayList是List接口的大小可变数组的实现,是有顺序的,实现了List中所有允许的API方法,允许重复的元素和null值,初始默认容量为10的,底层是数组结构。

  • 构造:
    • ArrayList():构造一个初始容量为10的ArrayList。
    • ArrayList(int initialCapacity):构造一个指定初始容量的ArrayList。
  • 方法:
    • boolean add(E e):将e追加到列表末尾。
    • void add(int index, E e);:将e插入到列表的index位置上。
    • boolean addAll(Collection<? extends E> c):将集合c整体追加到列表末尾。
    • boolean addAll(int index, Collection<? extends E> c):将集合c整体插入到列表的index位置上。
    • E get(int index):获取index位置上的元素。
    • int indexOf(Object o):返回o在列表中第一次出现的位置。
    • int lastIndexOf(Object o):返回o在列表中最后一次出现的位置。
    • boolean equals(Object o):判断两个列表内容是否相同。
    • boolean contains(Object o):判断列表中是否包含o。
    • boolean containsAll(Collection<?> c):判断列表中是否包含c集合的内容。
    • boolean isEmpty():判断列表是否为空。
    • int size():返回列表长度。
    • Object[] toArray():将列表转换为Object数组格式。
    • E set(int index, E e):将index位置上的元素替换成e。
    • List<E> subList(int a, int b):在原列表中从位置a截取到位置b,包括a不包括b。
    • E remove(int index):移除原列表中index位置上的元素。
    • boolean remove(Object o):移除原列表中的o元素。
    • boolean removeAll(Collection<?> c):移除原列表中和集合c相同的元素。
    • boolean retainAll(Collection<?> c):仅保留原列表中和集合c相同的元素。
    • void clear():清空列表中所有元素。
  • 遍历:可以使用for或者for-each进行遍历。

源码: /javase-advanced/

  • src: c.y.collection.ArrayListTest
/**
 * @author yap
 */
public class ArrayListTest {

    private ArrayList<String> arrayList;

    @Before
    public void before() {
        arrayList = new ArrayList<>(10);
    }

    @Test
    public void create() {
        arrayList.add("China");
        arrayList.add("Japan");
        arrayList.add(1, "Korea");
        arrayList.add(1, "Thailand");

        List<String> europe = new ArrayList<>();
        europe.add("UK");
        europe.add("France");
        arrayList.addAll(europe);

        List<String> africa = new ArrayList<>();
        africa.add("Congo");
        africa.add("Egypt");
        arrayList.addAll(1, africa);

        System.out.println("add over: " + arrayList);
    }

    @Test
    public void retrieve() {
        this.create();
        List<String> europe = new ArrayList<>();
        europe.add("UK");
        europe.add("France");

        System.out.println(arrayList.get(0));
        System.out.println(arrayList.indexOf("China"));
        System.out.println(arrayList.lastIndexOf("UK"));
        System.out.println(arrayList.equals(europe));
        System.out.println(arrayList.contains("Japan"));
        System.out.println(arrayList.containsAll(europe));
        System.out.println(arrayList.isEmpty());
        System.out.println(arrayList.size());
        System.out.println(arrayList.toArray()[0]);
    }

    @Test
    public void update() {
        this.create();

        arrayList.set(1, "UK");
        System.out.println(arrayList);
    }

    @Test
    public void delete() {
        this.create();
        List<String> europe = new ArrayList<>();
        europe.add("UK");
        europe.add("France");
        List<String> africa = new ArrayList<>();
        africa.add("Congo");
        africa.add("Egypt");

        System.out.println(arrayList.subList(0, 3));
        System.out.println(arrayList.remove(1));
        System.out.println(arrayList.remove("Egypt"));
        arrayList.removeAll(europe);
        arrayList.retainAll(africa);
        arrayList.clear();
    }

    @Test
    public void iteratorByFor() {
        this.create();
        for (int i = 0, j = arrayList.size(); i < j; i++) {
            System.out.print(arrayList.get(i) + "\0");
        }
    }

    @Test
    public void iteratorByForEach() {
        this.create();
        for (String str : arrayList) {
            System.out.print(str + "\0");
        }
    }
}

2.2 LinkedList实现类

概念: LinkedList是List接口的链表的实现,实现了List中所有允许的API方法,允许重复的元素和null值,底层是链表结构。

  • 构造:LinkedList():构造一个初始链表。
  • 方法:这里主要使用LinkedList专属的方法,父接口List中的方法同ArrayList。
    • void addFirst(E e):将e添加到链表开头。
    • void push(E e):将e添加到链表开头,底层调用的 addFirst()
    • boolean offerFirst(E e):将e添加到链表开头,底层调用的 addFirst()
    • void addLast(E e):将e添加到链表结尾。
    • boolean offer(E e):将e添加到链表结尾,底层调用的 add()
    • boolean offerLast(E e):将e添加到链表结尾,底层调用的 addLast()
    • E get(int index):获取index位置上的元素。
    • E getFirst():查看链表头,空列表抛异常。
    • E element():查看链表头,底层调用的 getFirst()
    • E peek():查看链表头,空列表返回null,1.5版本。
    • E peekFirst():查看链表头,空列表返回null,1.6版本。
    • E getLast():查看链表尾,空列表抛异常。
    • E peekLast():查看链表尾,空列表返回null,1.6版本。
    • E set(int index, E e):将index位置上的元素替换成e。
    • E poll():移除头并返回头,空列表返回null,1.5版本。
    • E pollFirst():移除头并返回头,空列表返回null,1.6版本。
    • E removeFirst():移除头并返回头,空列表抛异常。
    • E pop():移除头并返回头,底层调用的 removeFirst(),1.5版本。
    • E remove():移除头并返回头,底层调用的 removeFirst(),1.6版本。
    • E removeLast():移除尾并返回尾,空列表抛异常
    • E pollLast():移除尾并返回尾,空列表返回null,1.6版本。
    • E remove(int index):根据角标获取并删除元素。
    • E remove(Object o):根据内容获取并删除元素。
    • boolean removeFirstOccurrence(Object o):删除第一次出现的指定元素。
    • boolean removeLastOccurrence(Object o):删除最后一次出现的指定元素。
  • 遍历:可以使用for或者for-each进行遍历。

源码: /javase-advanced/

  • src: c.y.collection.LinkedListTest
/**
 * @author yap
 */
public class LinkedListTest {

    private LinkedList<String> linkedList;

    @Before
    public void before() {
        linkedList = new LinkedList<>();
    }

    @Test
    public void create() {
        linkedList.add("Korea");
        linkedList.add("Japan");
        linkedList.addFirst("China");
        linkedList.addLast("Thailand");
        linkedList.offer("UK");
        linkedList.offerLast("US");
        linkedList.offerFirst("France");
        linkedList.push("Congo");

        System.out.println("add over: " + linkedList);
    }

    @Test
    public void retrieve() {
        this.create();
        System.out.println(linkedList.get(0));
        System.out.println(linkedList.element());
        System.out.println(linkedList.getFirst());
        System.out.println(linkedList.getLast());
        System.out.println(linkedList.peek());
        System.out.println(linkedList.peekFirst());
        System.out.println(linkedList.peekLast());
    }

    @Test
    public void update() {
        this.create();
        linkedList.set(1, "UK");
        System.out.println(linkedList);
    }

    @Test
    public void remove() {
        this.create();
        System.out.println(linkedList.poll());
        System.out.println(linkedList.pollFirst());
        System.out.println(linkedList.pollLast());
        System.out.println(linkedList.pop());
        System.out.println(linkedList.remove());
        System.out.println(linkedList.remove(0));
        System.out.println(linkedList.remove("UK"));
        System.out.println(linkedList.removeFirst());
        System.out.println(linkedList.removeLast());
        System.out.println(linkedList.removeFirstOccurrence("Japan"));
        System.out.println(linkedList.removeLastOccurrence("US"));
    }

    @Test
    public void iteratorByFor() {
        this.create();
        for (int i = 0, j = linkedList.size(); i < j; i++) {
            System.out.print(linkedList.get(i) + "\0");
        }
    }

    @Test
    public void iteratorByForEach() {
        this.create();
        for (String str : linkedList) {
            System.out.print(str + "\0");
        }
    }
}

2.3 Stack实现类

概念: Stack类继承自Vector类(List的一个同步实现),是栈结构的工具类:

  • 构造:Stack() 实例化一个空栈。
  • 方法:
    • E push(E item):将元素推送到此栈结构的栈顶,并返回此元素。
    • E peek():查看栈顶元素,对空栈进行此操作,会抛异常。
    • E pop():移除并返回栈顶元素,对空栈进行此操作,会抛异常。
    • boolean empty():测试此栈是否为空。
  • 遍历:可以使用for-each进行遍历。

源码: /javase-advanced/

  • src: c.y.collection.StackTest
/**
 * @author yap
 */
public class StackTest {

    private Stack<Integer> stack;

    @Before
    public void before() {
        stack = new Stack<>();
    }

    @Test
    public void create() {
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println("create over: " + stack);
    }

    @Test
    public void retrieve() {
        this.create();
        System.out.println(stack.peek());
        System.out.println(stack.search(3));
    }

    @Test
    public void delete() {
        this.create();
        System.out.println(stack.pop());
        System.out.println(stack);
    }

    @Test
    public void iteratorByForEach() {
        for (int e : stack) {
            System.out.println(e);
        }
    }

    @Test
    public void iteratorByPop() {
        while (!stack.isEmpty()) {
            System.out.print(stack.pop() + "\0");
        }
    }
}

3. Set接口

概念: Set接口是相对无序(输入和输出不同)的一种容器,且不支持重复数据,并且最多包含一个null元素。

3.1 HashSet实现类

概念: HashSet底层满足Hash分布,无序不同步,是最常用的一种Set实现类。

  • 构造:
    • HashSet<>():创建一个默认初始容量的HashSet。
    • HashSet<>(int initialCapacity):创建一个指定初始容量的HashSet。
  • 方法:大部分的方法和List是一致的。
    • int hashCode():对于集合来说,返回的是集合中所有元素的hashCode之和,空集合返回0。
  • 遍历:可以使用for-each来遍历

源码: /javase-advanced/

  • src: c.y.collection.HashSetTest
/**
 * @author yap
 */
public class HashSetTest {

    private HashSet<String> hashSet;

    @Before
    public void before() {
        hashSet = new HashSet<>(0);
    }

    @Test
    public void deduplication() {
        System.out.println(hashSet.hashCode());
        hashSet.add("a");
        hashSet.add("b");
        System.out.println(hashSet.hashCode());
        hashSet.add("b");
        System.out.println(hashSet.hashCode());
    }

    @Test
    public void iteratorByForEach() {
        int times = 20;
        for (int i = 0; i < times; i++) {
            hashSet.add(i + "");
        }
        for (String str : hashSet) {
            System.out.print(str + "\0");
        }
    }
}

3.2 TreeSet实现类

概念: TreeSet的底层是二叉树结构,可以对存储的内容进行排序,线程不同步。

  • TreeSet会对实现了 Comparable 的接口的类进行自然排序(默认可改),如String、Integer等。
  • TreeSet允许指定自定义的比较器并作用在集合中元素的排序过程中。
  • 如果我们要添加的元素即没有实现 Comparable 接口,TreeSet中也没有指定自定义比较器,则无法使用TreeSet存贮。

源码: /javase-advanced/

  • src: c.y.collection.TreeSetTest.naturalSort()
/**
 * @author yap
 */
public class TreeSetTest {
    @Test
    public void naturalSort() {
        TreeSet<String> treeSet = new TreeSet<>();
        treeSet.add("abc");
        treeSet.add("aac");
        treeSet.add("abb");
        treeSet.add("acc");
        treeSet.add("3");
        treeSet.add("1");
        treeSet.add("2");
        System.out.println(treeSet);
    }
}

3.2.1 实现比较能力

概念: 如果想让某个自定义类也具有能比较的能力,可以效仿String或Integer,让该类实现 Comparable 接口,然后在重写方法中定义比较规则:

  • 重写:int compareTo(T o)
    • param1: 参与比较的参数,它会与上一个o进行比较。
    • return: 返回正整数表示p1在前,负整数表示p2在前,0表示相等并去重。

源码: /javase-advanced/

  • src: c.y.collection.TreeSetTest.sortByComparable()
/**
 * @author yap
 */
public class TreeSetTest {

    private static class Student implements Comparable<Student> {
        private String name;
        private int age;

        Student(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public int compareTo(Student student) {
            String prevName = this.name;
            String nextName = student.getName();
            int prevAge = this.age;
            int nextAge = student.getAge();
            return prevAge == nextAge ? prevName.compareTo(nextName) : prevAge - nextAge;
        }

        @Override
        public String toString() {
            return "Student [name=" + name + ", age=" + age + "]";
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Student student = (Student) o;
            return age == student.age &&
                    Objects.equals(name, student.name);
        }

        @Override
        public int hashCode() { return Objects.hash(name, age);
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }
    }
    
    @Test
    public void sortByComparable() {
        TreeSet<Student> treeSet = new TreeSet<>();
        Student studentA = new Student("a", 50);
        Student studentB = new Student("c", 30);
        Student studentC = new Student("b", 30);
        treeSet.add(studentA);
        treeSet.add(studentB);
        treeSet.add(studentC);
        System.out.println(treeSet);
    }

3.2.2 自定义比较器

概念: TreeSet在构造的时候,可以直接指定一个 Comparator 的实现类作为比较器,然后在重写方法中定义比较规则:

  • 构造:TreeSet(Comparator<? super E> comparator)
  • 重写:int compare(T o1, T o2)
    • param1: 参与比较的第1个参数。
    • param2: 参与比较的第2个参数。
    • return: 返回正整数表示p1在前,负整数表示p2在前,0表示相等并去重。

源码: /javase-advanced/

  • src: c.y.collection.TreeSetTest.sortByComparator()
/**
 * @author yap
 */
public class TreeSetTest {

    private static class CustomComparator implements Comparator<Person> {
        @Override
        public int compare(Person personA, Person personB) {
            String nameOfPersonA = personA.getName();
            String nameOfPersonB = personB.getName();
            int result = nameOfPersonA.compareTo(nameOfPersonB);
            if (result == 0) {
                int ageOfPersonA = personA.getAge();
                int ageOfPersonB = personB.getAge();
                result = ageOfPersonA - ageOfPersonB;
            }
            return result;
        }
    }

    private static class Person {
        private String name;
        private int age;

        Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Person person = (Person) o;
            return age == person.age &&
                    Objects.equals(name, person.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }

        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }
    }

    @Test
    public void sortByComparator() {
        Set<Person> treeSet = new TreeSet<>(new CustomComparator());
        treeSet.add(new Person("b", 18));
        treeSet.add(new Person("b", 15));
        treeSet.add(new Person("a", 9));
        treeSet.add(new Person("a", 9));
        System.out.println(treeSet);
    }
}

3.3 EnumSet实现类

概念: EnumSet支持通过静态方法 allOf(枚举类.class) 将指定的枚举类中的所有枚举常量转成一个Set结构。

源码: /javase-advanced/

  • src: c.y.collection.EnumSetTest
/**
 * @author yap
 */
public class EnumSetTest {

    private enum Color {
        /**
         * some color
         */
        RED, GREEN, BLUE, YELLOW, WHITE, BLACK, PINK, GRAY
    }

    @Test
    public void enumToSet() {
        EnumSet<Color> colors = EnumSet.allOf(Color.class);
        for (Color color : colors) {
            System.out.print(color.toString() + "\0");
        }
    }
}

4. Queue容器

概念: Queue 接口继承自 Collection 接口,内部是队列结构,通常是以FIFO的方式操作元素的,但是优先级队列或LIFO队列等特殊队列例外。

  • boolean add(E e):将e加入到对列中。
  • boolean offer(E e):将e加入到对列中,当队列有容量限制的时候,此方法通常优于 add()
  • E element():查看队列头元素,空队列抛异常。
  • E peek():查看队列头元素,空队列返回null。
  • E remove():移除并返回队列头元素,空队列抛异常。
  • E poll():移除并返回队列头元素,空队列返回null。

源码: /javase-advanced/

  • src: c.y.collection.QueueTest
/**
 * @author yap
 */
public class QueueTest {

    private Queue<Integer> queue;

    @Before
    public void before() {
        queue = new LinkedList<>();
    }

    @Test
    public void create() {
        queue.add(1);
        queue.add(2);
        queue.offer(3);
        queue.offer(4);
        System.out.println("create over: " + queue);
    }

    @Test
    public void retrieve() {
        this.create();
        System.out.println("element: " + queue.element());
        System.out.println("peek: " + queue.peek());
    }

    @Test
    public void delete() {
        this.create();
        System.out.println(queue.remove());
        System.out.println(queue.poll());
        System.out.println(queue);
    }

    @Test
    public void iteratorByForEach() {
        this.create();
        for (int e : queue) {
            System.out.print(e + "\0");
        }
    }

    @Test
    public void iteratorByPoll() {
        this.create();
        while (!queue.isEmpty()) {
            System.out.println("poll: " + queue.poll());
        }
    }
}

5. Map接口

概念: Map一般称为映射,是一种以键值对(Entry)的方式存储数据的容器,不能包含重复的key,每个key最多只能映射到一个值。

Map接口实际上是Set接口的底层实现,包括Set接口的实现类底层调用的也是对应的Map接口的实现类。

5.1 HashMap实现类

概念: HashMap是基于哈希表的Map接口的非同步实现类,允许使用null值和null键,此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

  • 构造:
    • HashMap<>():创建一个默认容量的HashMap。
    • HashMap<>(int initialCapacity):创建一个指定初始容量的HashMap。
  • 方法:
    • V put(K key, V value):向HashMap中存值,相同的key会覆盖。
    • void putAll(Map<? extends K, ? extends V> m):将另一个Map整体添加到当前Map中。
    • V get(Object key):在Map中将指定的key对应的value取出来,没有返回null。
    • boolean containsKey(Object key):判断Map中是否存在指定的key。
    • boolean containsValue(Object value):判断Map中是否存在指定的value。
    • boolean isEmpty():判断Map是否为空。
    • int size():返回Map中的键值对Entry的个数。
    • Collection<V> values():返回Map中的所有value的collection集合实例。
    • Set<K> keySet():返回Map中的所有key的Set集合实例。
    • V remove(Object key):移除Map中指定的key对应的value,并返回。
      • 如果想删除null,不能加双引号。
    • void clear():移除Map中所有的键值对Entry。
    • Set<Map.Entry<K,V>> entrySet():返回Map中所有的键值对Entry的Set集合。
  • 遍历:可以辅助 keySet()entrySet() 完成遍历。

源码: /javase-advanced/

  • src: c.y.collection.HashMapTest
/**
 * @author yap
 */
public class HashMapTest {

    private HashMap<String, Object> hashMap;

    @Before
    public void before() {
        hashMap = new HashMap<>(5);
    }

    @Test
    public void create() {
        hashMap.put("gong-zuo", "");
        hashMap.put("gong-zuo", "singer");
        hashMap.put("job", "singer");
        hashMap.put("t", null);
        hashMap.put(null, "k");
        hashMap.put(null, null);

        HashMap<String, Object> newHashMap = new HashMap<>(5);
        hashMap.put("a", 1);
        hashMap.put("b", 2);
        hashMap.putAll(newHashMap);

        System.out.println("create over: " + hashMap);
    }

    @Test
    public void retrieve() {
        this.create();
        System.out.println(hashMap.get("gong-zuo"));
        System.out.println(hashMap.containsKey("gong-zuo"));
        System.out.println(hashMap.containsValue("singer"));
        System.out.println(hashMap.isEmpty());
        System.out.println(hashMap.size());
        System.out.println(hashMap.values());
        System.out.println(hashMap.keySet());
    }

    @Test
    public void delete() {
        this.create();
        System.out.println(hashMap.remove("job"));
        hashMap.remove(null);
        hashMap.clear();
    }

    @Test
    public void iteratorByEntrySet() {
        this.create();
        Set<Map.Entry<String, Object>> entries = hashMap.entrySet();
        for (Map.Entry<String, Object> e : entries) {
            System.out.println(e.getKey() + ": " + e.getValue());
        }
    }

    @Test
    public void iteratorByKeySet() {
        this.create();
        Set<String> keys = hashMap.keySet();
        for (String key : keys) {
            System.out.println(key + ": " + hashMap.get(key));
        }
    }

}

5.2 TreeMap实现类

概念: TreeMap是基于红黑树(Red-Black tree)的Map实现,该TreeMap根据其key的自然顺序进行排序,也可以在构造的时候指定自定义Comparator。

  • 构造:
    • TreeMap():创建一个默认比较器的HashMap。
    • TreeMap(Comparator<? super K> comparator):创建一个指定比较器的HashMap。
  • 方法:大部分方法和HashMap是类似的:
    • Map.Entry<K,V> ceilingEntry(K key):查询大于或等于key的所有值中的最小Entry。
    • K ceilingKey(K key):查询大于或等于key的所有值中的最小key。
    • Map.Entry<K,V> higherEntry(K key):查询大于key的所有值中的最小Entry。
    • K higherKey(K key):查询大于key的所有值中的最小Key。
    • Map.Entry<K,V> floorEntry(K key):查询小于或等于key的所有值中的最大Entry。
    • K floorKey(K key):查询小于或等于key的所有值中的最大Key。
    • Map.Entry<K,V> lowerEntry(K key):查询小于key的所有值中的最大Entry。
    • K lowerKey(K key):查询小于key的所有值中的最大Key。
    • Comparator<? super K> comparator():查询Map的自定义比较器实例,没有返回null。
    • NavigableMap<K, V> descendingMap():逆序排列所有Entry。
    • NavigableSet<K> descendingKeySet():逆序排列所有key。
    • Map.Entry<K,V> firstEntry():查询第一个Entry。
    • K firstKey():查询第一个key。
    • Map.Entry<K,V> lastEntry():查询最后一个Entry。
    • K lastKey():查询最后一个key。
    • SortedMap<K,V> headMap(K toKey):将Map截取到toKey,不包括toKey。
      • 追加 true 参数表示将Map截取到toKey,包括toKey。
    • SortedMap<K,V> tailMap(K fromKey):将Map从fromKey开始向后截取,包括fromKey。
      • 追加 false 参数表示将Map从fromKey开始截取,不包括fromKey。
    • SortedMap<K,V> subMap(K fromKey, K toKey):从fromKey向后截取到toKey,左闭右开。
      • fromKey和toKey后面均可追加true或false,表示包括或不包括。

源码: /javase-advanced/

  • src: c.y.collection.TreeMapTest
/**
 * @author yap
 */
public class TreeMapTest {

    private TreeMap<String, Object> treeMap;

    @Before
    public void before() {
        treeMap = new TreeMap<>();
    }

    @Test
    public void create() {
        treeMap.put("1", "a");
        treeMap.put("3", "c");
        treeMap.put("2", "b");
        treeMap.put("4", "f");
        treeMap.put("5", "e");
        System.out.println(treeMap);
    }

    @Test
    public void retrieve() {
        this.create();
        System.out.println(treeMap.ceilingEntry("2"));
        System.out.println(treeMap.ceilingKey("4"));
        System.out.println(treeMap.higherEntry("2"));
        System.out.println(treeMap.higherKey("2"));

        System.out.println(treeMap.floorEntry("4"));
        System.out.println(treeMap.floorKey("2"));
        System.out.println(treeMap.lowerEntry("4"));
        System.out.println(treeMap.lowerKey("2"));

        System.out.println(treeMap.comparator());

        System.out.println(treeMap.descendingMap());
        System.out.println(treeMap.descendingKeySet());

        System.out.println(treeMap.firstEntry());
        System.out.println(treeMap.firstKey());
        System.out.println(treeMap.lastEntry());
        System.out.println(treeMap.lastKey());
    }

    @Test
    public void intercept() {
        this.create();
        System.out.println(treeMap.headMap("4"));
        System.out.println(treeMap.headMap("4", true));
        System.out.println(treeMap.tailMap("3"));
        System.out.println(treeMap.tailMap("3", false));
        System.out.println(treeMap.subMap("2", "4"));
        System.out.println(treeMap.subMap("2", false, "3", true));
    }
}

5.3 EnumMap实现类

概念: EnumMap 可以将枚举常量作为 KEY,将一个字符串作为 VALUE

源码: /javase-advanced/

  • src: c.y.collection.EnumMapTest
/**
 * @author yap
 */
public class EnumMapTest {

    private enum Color {
        /**
         * some color
         */
        RED, GREEN, BLUE, YELLOW, WHITE, BLACK, PINK, GRAY
    }

    private EnumMap<Color, String> enumMap;

    @Before
    public void before() {
        enumMap = new EnumMap<>(Color.class);
    }

    @Test
    public void enumMap() {
        enumMap.put(Color.RED, "red");
        enumMap.put(Color.GREEN, "green");
        enumMap.put(Color.BLUE, "blue");
        enumMap.put(Color.YELLOW, "yellow");
        enumMap.put(Color.WHITE, "white");
        enumMap.put(Color.BLACK, "black");
        enumMap.put(Color.PINK, "pink");
        enumMap.put(Color.GRAY, "gray");

        Set<Map.Entry<Color, String>> colors = enumMap.entrySet();
        for (Map.Entry<Color, String> e : colors) {
            System.out.println(e.getKey() + ": " + e.getValue());
        }
    }
}

6. 迭代器

概念: 除了使用for或foreach循环外,我们更建议使用迭代器来遍历列表:

  • ArrayList 通过 iterator() 获得 Iterator 实例:
    • Iterator 默认指针在0号位置之前。
    • hasNext() + next() :配合完成列表的迭代。
    • 它可以通过 remove():删除当前指针所在位置的内容。
  • ArrayList 通过 listIterator() 获得 ListIterator 实例:
    • 它是 Iterator 接口的子类,只能遍历list,允许使用 Iterator 的所有API方法。
    • listIterator(int pos) 可以灵活地指定初始指针的位置。
    • hasPrevious()previous():配合完成列表的反向迭代,ListIterator 专属。
    • set(E e):替换当前指针所在位置的内容,ListIterator 专属。

源码: /javase-advanced/

  • src: c.y.collection.IteratorTest
/**
 * @author yap
 */
public class IteratorTest {

    private List<Integer> arrayList = null;

    @Before
    public void before() {
        for (int i = 0, j = 20; i < j; i++) {
            arrayList.add(i);
        }
    }

    @Test
    public void iterator() {
        Iterator<Integer> iterator = arrayList.iterator();
        while (iterator.hasNext()) {
            int e = iterator.next();
            if (e == 1) {
                iterator.remove();
            }
            System.out.print(e + "\0");
        }
    }

    @Test
    public void listIterator() {
        ListIterator<Integer> listIter = arrayList.listIterator(0);
        while (listIter.hasNext()) {
            int e = listIter.next();
            if (e == 3) {
                listIter.set(300);
            }
            if (e == 5) {
                listIter.remove();
            }
            System.out.print(e + "\0");
        }
    }

    @Test
    public void reverseListIterator() {
        ListIterator<Integer> listIter = arrayList.listIterator(arrayList.size());
        while (listIter.hasPrevious()) {
            System.out.print(listIter.previous() + "\0");
        }
    }
}

Iterator迭代器的效率比for和foreach更高。