网络知识 娱乐 【面试专栏】第八篇:Java基础:集合篇-集合总结、集合工具类

【面试专栏】第八篇:Java基础:集合篇-集合总结、集合工具类

文章目录

    • 集合对比&选择
    • 集合工具java.util.Collections
      • 列表排序(指定顺序)
      • 列表快速查询下标
      • 反转列表
      • 随机打乱列表
      • 交换指定列表两个元素位置
      • 填充list
      • 拷贝集合(对元素而言是拷贝引用)
      • 最大、最小值
      • 集合出现次数(统计集合内元素的频次)
      • map 转set
      • 整体移动前n个元素到集合后面(或者后n个到前面)
      • 不可变包装(用于集合元素固定不可修改)
      • 同步集合包装(用于生成线程安全集合)
      • 单元素集合包装(避免new 集合返回)/空集合包装 (避免反回null 或者new 集合)
    • 探索java.util.Arrays#sort排序算法

集合对比&选择

通过前面几天的集合文章:

  • 【面试专栏】第三篇:Java基础:集合篇-List、Queue
  • 【面试专栏】第四篇:Java基础:集合篇-Map、HashMap、Hashtable
  • 【面试专栏】第五篇:Java基础:集合篇-LinkedHashMap、ConcurrentHashMap、TreeMap
  • 【面试专栏】第六篇:Java基础:集合篇-HashSet、TreeSet
  • 【面试专栏】第七篇:Java基础:集合篇-LinkedHashSet、BitSet、CopyOnWriteArraySet

简单总结回顾一下:

Map 接口和 Collection 接口是所有集合框架的父接口;
Collection 接口的子接口包括:Set 接口、List 接口和Queue接口;
Map 接口的实现类主要有:HashMap、TreeMap、LinkedHashMap、Hashtable、ConcurrentHashMap 以及 Properties 等;
Set 接口的实现类主要有:HashSet、TreeSet、LinkedHashSet 等;
List 接口的实现类主要有:ArrayList、LinkedList、Stack 、Vector以及CopyOnWriteArrayList 等;
Queue接口的主要实现类有:ArrayDeque、ArrayBlockingQueue、LinkedBlockingQueue、PriorityQueue等;

  • 有序选择List 、无序去重选择Set
  • 有序选择TreeMap、无序选择HashMap
  • 线程安全有:Vector、Stack、CopyOnWriteArrayList、Hashtable、ConcurrentHashMap、CopyOnWriteArraySet
  • 线程安全优先选择:CopyOnWriteArrayList、CopyOnWriteArraySet、ConcurrentHashMap

今天再介绍一种新的方式集合工具类实现线程安全。

集合工具java.util.Collections

列表排序(指定顺序)

需要注意列表如果为空会npe , 内部使用的其实是java.util.Arrays#sort,这个在后面单独介绍

  • java.util.Collections#sort(java.util.List) 默认排序
  • java.util.Collections#sort(java.util.List, java.util.Comparator) 带参数,可以指定排序类(这里也是和jdk8 lambda 结合后很便捷的点)

列表快速查询下标

通过jdk封装的快速查询元素所在位置

  • java.util.Collections#binarySearch(java.util.List<? extends java.lang.Comparable>, T)
  • java.util.Collections#binarySearch(java.util.List, T, java.util.Comparator)

反转列表

  • java.util.Collections#reverse

随机打乱列表

一些需要随机展示的场景需要打乱列表

  • java.util.Collections#shuffle(java.util.List)

交换指定列表两个元素位置

  • java.util.Collections#swap(java.util.List, int, int)

填充list

将指定元素填充满列表

  • java.util.Collections#fill

拷贝集合(对元素而言是拷贝引用)

  • java.util.Collections#copy

最大、最小值

内部循环一遍根据排序找出最大最小返回

  • java.util.Collections#min(java.util.Collection)
  • java.util.Collections#min(java.util.Collection, java.util.Comparator)
  • java.util.Collections#max(java.util.Collection)
  • java.util.Collections#max(java.util.Collection, java.util.Comparator)

集合出现次数(统计集合内元素的频次)

可以统计null的次数

  • java.util.Collections#frequency

map 转set

  • java.util.Collections#newSetFromMap

整体移动前n个元素到集合后面(或者后n个到前面)

当distance为正数时,将List集合的后distance个元素“整体”移到前面;当distance为负数时,将list集合的前distance个元素“整体”移到后边。该方法不会改变集合的长度。

  • java.util.Collections#rotate

不可变包装(用于集合元素固定不可修改)

所有类型的集合都封装了一个对应的方法,实现原理就是内部实现了一个集合的方法,调用修改集合修改方法抛出异常

所以对于集合内对象的值是可以修改的,集合与对象的引用是不允许修改了

  • java.util.Collections#unmodifiableCollection
  • java.util.Collections#unmodifiableSet
  • java.util.Collections#unmodifiableSortedSet
  • java.util.Collections#unmodifiableList
  • java.util.Collections#unmodifiableMap

同步集合包装(用于生成线程安全集合)

生成一个线程安全的集合对象,实现原理就是内部实现了一个集合的同步方法,同步类就是集合自身引用,调用修改方法时 使用synchronized 锁住自身对象

拿一个举例


 /**
     * @serial include
     */
    static class SynchronizedCollection implements Collection, Serializable {
        private static final long serialVersionUID = 3053995032091335093L;

        final Collection c;  // Backing Collection
        final Object mutex;     // Object on which to synchronize

        SynchronizedCollection(Collection c) {
            this.c = Objects.requireNonNull(c);
            mutex = this;
        }

        SynchronizedCollection(Collection c, Object mutex) {
            this.c = Objects.requireNonNull(c);
            this.mutex = Objects.requireNonNull(mutex);
        }

        public int size() {
            synchronized (mutex) {return c.size();}
        }
        public boolean isEmpty() {
            synchronized (mutex) {return c.isEmpty();}
        }
        public boolean contains(Object o) {
            synchronized (mutex) {return c.contains(o);}
        }
        public Object[] toArray() {
            synchronized (mutex) {return c.toArray();}
        }
        public  T[] toArray(T[] a) {
            synchronized (mutex) {return c.toArray(a);}
        }

        public Iterator iterator() {
            return c.iterator(); // Must be manually synched by user!
        }

        public boolean add(E e) {
            synchronized (mutex) {return c.add(e);}
        }
        public boolean remove(Object o) {
            synchronized (mutex) {return c.remove(o);}
        }

        public boolean containsAll(Collection coll) {
            synchronized (mutex) {return c.containsAll(coll);}
        }
        public boolean addAll(Collection coll) {
            synchronized (mutex) {return c.addAll(coll);}
        }
        public boolean removeAll(Collection coll) {
            synchronized (mutex) {return c.removeAll(coll);}
        }
        public boolean retainAll(Collection coll) {
            synchronized (mutex) {return c.retainAll(coll);}
        }
        public void clear() {
            synchronized (mutex) {c.clear();}
        }
        public String toString() {
            synchronized (mutex) {return c.toString();}
        }
        // Override default methods in Collection
        @Override
        public void forEach(Consumer consumer) {
            synchronized (mutex) {c.forEach(consumer);}
        }
        @Override
        public boolean removeIf(Predicate filter) {
            synchronized (mutex) {return c.removeIf(filter);}
        }
        @Override
        public Spliterator spliterator() {
            return c.spliterator(); // Must be manually synched by user!
        }
        @Override
        public Stream stream() {
            return c.stream(); // Must be manually synched by user!
        }
        @Override
        public Stream parallelStream() {
            return c.parallelStream(); // Must be manually synched by user!
        }
        private void writeObject(ObjectOutputStream s) throws IOException {
            synchronized (mutex) {s.defaultWriteObject();}
        }
    }

单元素集合包装(避免new 集合返回)/空集合包装 (避免反回null 或者new 集合)

这两种我认为是一种更优雅、更高性能(避免了创建很多个集合)的写法,但是需要注意在上层使用的时候不能直接添加元素,不然会抛出异常

单元素集合实现了集合方法,内部只保存一个元素

  • java.util.Collections#singleton
  • java.util.Collections#singletonList
  • java.util.Collections#singletonMap

空集合实现了集合方法,内部不存储元素,同时设置了静态变量,全局只有一个空集合

  • java.util.Collections#emptySet
  • java.util.Collections#emptyMap

探索java.util.Arrays#sort排序算法