Erlo

【Guava】集合工具类-Immu#sql_table#&Lists&Maps&Sets

2025-03-31 08:29:24 发布   117 浏览  
页面报错/反馈
收藏 点赞

Immutable

《Effective Java》Item1)所述,在设计类的时候,倾向优先使用静态工厂方法(static factory method)而非构造函数(constructor)创建对象,优点在于:

  1. 静态工厂方法多了一层名称信息,比构造函数更富表达性。
  2. 可以更灵活地创建对象,比如缓式初始化,缓存已创建对象。
  3. 静态方法内部返回的对象类型,可以是其声明类型的子类。

同样,如《Effective Java》Item17所述,需要最小化可变性,ImmutableList遵循了最佳实践。首先,ImmutableList不可以通过构造函数实例化,更准确地说,不可以在package外部通过构造函数实例化。

而在程序设计中使用不可变对象,也可以提高代码的可靠性和可维护性,其优势包括:

  1. 线程安全性(Thread Safety):不可变对象是线程安全的,无需同步操作,避免了竞态条件
  2. 安全性:可以防止在程序运行时被意外修改,提高了程序的安全性
  3. 易于理解和测试:不可变对象在创建后不会发生变化,更容易理解和测试
  4. 克隆和拷贝:不可变对象不需要实现可变对象的复制(Clone)和拷贝(Copy)逻辑,因为它们的状态不可变,克隆即是自己

创建对象的不可变拷贝是一项很好的防御性编程技巧。Guava为所有JDK标准集合类型和Guava新集合类型都提供了简单易用的不可变版本。JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式.

JDK不可变集合存在的问题

JDK 的 Collections 提供了 Unmodified Collections 不可变集合,但仅仅是通过装饰器模式提供了一个只读的视图,unmodifiableList本身是无法进行add等修改操作,但并没有阻止对原始集合的修改操作,所以说Collections.unmodifiableList实现的不是真正的不可变集合。

List list=new ArrayList();
list.add("a");
list.add("b");
list.add("c");

//通过list创建一个不可变的unmodifiableList集合
List unmodifiableList = Collections.unmodifiableList(list);
System.out.println(unmodifiableList);//[a,b,c]

//通过list添加元素
list.add("ddd");
System.out.println("往list添加一个元素:" + list);//[a,b,c,ddd]
System.out.println("通过list添加元素之后的unmodifiableList:" + unmodifiableList);[]//[a,b,c,ddd]

 //通过unmodifiableList添加元素
unmodifiableList.add("eee");//报错
System.out.println("往unmodifiableList添加一个元素:" + unmodifiableList);

  • 笨重而且累赘:不能舒适地用在所有想做防御性拷贝的场景;
  • 不安全:要保证没人通过原集合的引用进行修改,返回的集合才是事实上不可变的;
  • 低效:包装过的集合仍然保有可变集合的开销,比如并发修改的检查、散列表的额外空间,等等。

Guava不可变集合案例

而 Guava 提供的不可变集合不是原容器的视图,而是原容器的一份拷贝,因此更加简单高效,确保了真正的不可变性。

但是还要注意,由于immutable只是copy了元容器本身,并不是deep copy,因此对原容器的引用的内容进行修改,也会影响immutableXXX

注意:每个Guava immutable集合类的实现都拒绝null值。如果确实需要能接受null值的集合类,可以考虑用Collections.unmodifiableXXX。

immutable集合可以有以下几种方式来创建:

  1. 用copyOf方法,比如,ImmutableSet.copyOf(set)
  2. 使用of方法,比如,ImmutableSet.of("a", "b", "c") 或者 ImmutableMap.of("a", 1, "b", 2)
  3. 使用Builder类:减少中间对象的创建,提高内存使用效率。
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
System.out.println("list:" + list);//[a, b, c]

ImmutableList imlist = ImmutableList.copyOf(list);
System.out.println("imlist:" + imlist);//[a, b, c]

ImmutableList imOflist = ImmutableList.of("seven", "seven1", "seven2");
System.out.println("imOflist:" + imOflist);//[seven, seven1, seven2]

ImmutableSortedSet imSortList = ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");
System.out.println("imSortList:" + imSortList);//[a, b, c, d]

list.add("seven");
System.out.println("list add a item after list:" + list);//[a, b, c, seven]
System.out.println("list add a item after imlist:" + imlist);//[a, b, c]

ImmutableSet imColorSet =
       ImmutableSet.builder()
             .add(new Color(0, 255, 255))
             .add(new Color(0, 191, 255))
             .build();

System.out.println("imColorSet:" + imColorSet); //[java.awt.Color[r=0,g=255,b=255], java.awt.Color[r=0,g=191,b=255]]

更智能的copyOf

ImmutableXXX.copyOf会在合适的情况下避免拷贝元素的操作。

ImmutableSet imSet = ImmutableSet.of("seven", "lisa", "seven1", "lisa1");
System.out.println("imSet:" + imSet);//[seven, lisa, seven1, lisa1]
ImmutableList imlist = ImmutableList.copyOf(imSet);
System.out.println("imlist:" + imlist);//[seven, lisa, seven1, lisa1]
ImmutableSortedSet imSortSet = ImmutableSortedSet.copyOf(imSet);
System.out.println("imSortSet:" + imSortSet);//[lisa, lisa1, seven, seven1]

List list = new ArrayList();
for (int i = 0; i  imInfolist = ImmutableList.copyOf(list.subList(2, 18));
System.out.println("imInfolist:" + imInfolist);//[2x, 3x, 4x, 5x, 6x, 7x, 8x, 9x, 10x, 11x, 12x, 13x, 14x, 15x, 16x, 17x]
int imInfolistSize = imInfolist.size();
System.out.println("imInfolistSize:" + imInfolistSize);//16
ImmutableSet imInfoSet = ImmutableSet.copyOf(imInfolist.subList(2, imInfolistSize - 3));
System.out.println("imInfoSet:" + imInfoSet);//[4x, 5x, 6x, 7x, 8x, 9x, 10x, 11x, 12x, 13x, 14x]

在这段代码中,ImmutableList.copyOf(imSet)会智能地直接返回 imSet.asList(),它是一个ImmutableSet的常量时间复杂度的List视图。

实际上,要实现copyOf方法,最简单的就是直接将底层的每个元素做深拷贝然后生成ImmutableList。但是对于所有情况都深拷贝的话,性能和存储开销必然比较大,那么源码里面是如何优化的呢?

所有不可变集合都有一个asList() 方法提供ImmutableList视图,让我们可以用列表形式方便地读取集合元素。例如,我们可以使用sortedSet.asList().get(k) 从 ImmutableSortedSet 中读取第k个最小元素。
asList()返回的ImmutableList 通常是(但并不总是)开销稳定的视图实现,而不是简单地把元素拷贝进List,也就是说,asList返回的列表视图通常比一般的列表平均性能更好,比如,在底层集合支持的情况下,它总是使用高效的contains方法。

源码如下:

// com.google.common.collect.ImmutableList#copyOf(java.util.Collection extends E>)
public static  ImmutableList copyOf(Collection extends E> elements) {
    //判断是否是不可变集合
    if (elements instanceof ImmutableCollection) {
        //如果传入的结合本身就是一个不可变集合,那么asList获取视图后返回;其实就是直接复用原来的collection
        ImmutableList list = ((ImmutableCollection)elements).asList();
        //判断是否是要返回局部视图:是的话重新构建->调用Arrays.copyOf做深拷;不是的话就复用原来的
        return list.isPartialView() ? asImmutableList(list.toArray()) : list;
    } else {//如果不是,则执行construct方法:底层调用Arrays.copyOf做深拷贝
        return construct(elements.toArray());
    }
}

// com.google.common.collect.ImmutableCollection#asList
public ImmutableList asList() {
    switch (this.size()) {
        case 0:
            // 返回一个空的不可变集合,这个空集合是个static final常量,可复用
            return ImmutableList.of();
        case 1:
            // 返回一个不可变的 SingletonImmutableList 集合
            return ImmutableList.of(this.iterator().next());
        default:
            return new RegularImmutableAsList(this, this.toArray());
    }
}

//com.google.common.collect.RegularImmutableAsList#RegularImmutableAsList(com.google.common.collect.ImmutableCollection, java.lang.Object[])
RegularImmutableAsList(ImmutableCollection delegate, Object[] array) {
    this(delegate, ImmutableList.asImmutableList(array));
}
RegularImmutableAsList(ImmutableCollection delegate, ImmutableList extends E> delegateList) {
    this.delegate = delegate;
    this.delegateList = delegateList;
}

实际上,ImmutableXXX.copyOf(ImmutableCollection)会试图对如下情况避免线性时间拷贝:

  • 在常量时间内使用底层数据结构是可能的:因为会获取视图后返回
  • 不会造成内存泄露:例如,有个很大的不可变集合ImmutableList hugeListImmutableList.copyOf(hugeList.subList(0, 10))就会显式地拷贝(如上源码,会判断是否是局部视图),以免不必要地持有hugeList的引用。
  • 不改变语义:所以ImmutableSet.copyOf(myImmutableSortedSet)都会显式地拷贝,因为和基于比较器的ImmutableSortedSet相比,ImmutableSet对hashCode()和equals有不同语义。

在可能的情况下避免线性拷贝,可以最大限度地减少防御性编程风格所带来的性能开销。

Guava集合和不可变对应关系

可变集合类型 可变集合源:JDK or Guava? Guava不可变集合
Collection JDK ImmutableCollection
List JDK ImmutableList
Set JDK ImmutableSet
SortedSet/NavigableSet JDK ImmutableSortedSet
Map JDK ImmutableMap
SortedMap JDK ImmutableSortedMap
Multiset Guava ImmutableMultiset
SortedMultiset Guava ImmutableSortedMultiset
Multimap Guava ImmutableMultimap
ListMultimap Guava ImmutableListMultimap
SetMultimap Guava ImmutableSetMultimap
BiMap Guava ImmutableBiMap
ClassToInstanceMap Guava ImmutableClassToInstanceMap
Table Guava ImmutableTable

Lists

private Lists() {
}

私有的构造方法,可以看到这是一个真正的功能函数,下面对其函数进行分析

功能函数

首先根据每一个函数的更能进行了分类:

功能 方法
创建ArrayList方法 1、newArrayList()
2、newArrayList(E... elements)
3、newArrayList(Iterable extends E> elements)
4、newArrayList(Iterator extends E> elements)
5、newArrayListWithCapacity(int initialArraySize)
6、newArrayListWithExpectedSize(int estimatedSize)
创建LinkedList方法 1、newLinkedList()
2、newLinkedList(Iterable extends E> elements)
创建CopyOnWriteArrayList方法 1、newCopyOnWriteArrayList()
2、newCopyOnWriteArrayList(Iterable extends E> elements)
创建自制List规则 1、asList(@Nullable E first, E[] rest)
2、asList(@Nullable E first, @Nullable E second, E[] rest)
List笛卡尔乘积 1、cartesianProduct(List extends List extends B>> lists)
2、cartesianProduct(List extends B>... lists)
List变形 transform(List fromList, Function super F, ? extends T> function)
分割list(作用之一:分页) partition(List list, int size)
将字符串作为字符数组进行操作 1、charactersOf(String string)
2、charactersOf(CharSequence sequence)
将list逆序 reverse(List list)

创建ArrayList方法

  1. 没有参数的创建ArrayList

    public static  ArrayList newArrayList() {
        return new ArrayList();//直接返回一个新的ArrayList容器
    }
    
  2. 传入一个数组,返回一个ArrayList

    public static  ArrayList newArrayList(E... elements) {
        //对数组进行判空处理
        Preconditions.checkNotNull(elements);
        // computeArrayListCapacity对当前数量进行优化
        int capacity = computeArrayListCapacity(elements.length);
        //这里根据优化后的数量进行创建一个新的ArrayList
        ArrayList list = new ArrayList(capacity);
        //将数组里面的元素都存储在List中
        Collections.addAll(list, elements);
        return list;
    }
    
    //目的是为了给定一个期望的元素数量(arraySize),计算出为了避免或减少动态扩容带来的开销,列表初始化时应该分配的容量
    @VisibleForTesting
    static int computeArrayListCapacity(int arraySize) {
        //确保arraySize非负数
        CollectPreconditions.checkNonnegative(arraySize, "arraySize");
        //确保最后的数值在 int范围内
        return Ints.saturatedCast(5L + (long)arraySize + (long)(arraySize / 10));
    }
    
  3. 传入一个集合顶级接口,然后返回一个ArrayList

    public static  ArrayList newArrayList(Iterable extends E> elements) {
        //对集合进行判空
        Preconditions.checkNotNull(elements);
        //根据传入的实际类型,进行分别处理
        return elements instanceof Collection ? new ArrayList(Collections2.cast(elements)):newArrayList((Iterator)elements.
    iterator());
    }
    
  4. 传入一个迭代器,返回一个ArrayList

    public static  ArrayList newArrayList(Iterator extends E> elements) {
        ArrayList list = newArrayList();
        //根据Iterators中的addAll方法将迭代器中的源码装入list集合中
        Iterators.addAll(list, elements);
        return list;
    }
    
  5. 传入想要的list长度,返回一个与传入值等长的ArrayList

    //直接返回一个新的ArrayList,并且长度为传入的长度
    public static  ArrayList newArrayListWithCapacity(int initialArraySize) {
        CollectPreconditions.checkNonnegative(initialArraySize, "initialArraySize");
        return new ArrayList(initialArraySize);
    }
    
  6. 传入一个想要的list长度,返回一个程序调优后的长度的ArrayList

    public static  ArrayList newArrayListWithExpectedSize(int estimatedSize) {
        return new ArrayList(computeArrayListCapacity(estimatedSize));//返回一个长度调优后的ArrayList
    }
    

创建LinkedList方法

  1. 不传入参数,直接返回一个LinkedList

    public static  LinkedList newLinkedList() {
        return new LinkedList();//直接返回一个LinkedList
    }
    
  2. 传入一个容器,返回一个LinkedList

    public static  LinkedList newLinkedList(Iterable extends E> elements) {
        LinkedList list = newLinkedList();
        //将传入的容器,使用Iterables的addAll方法进行的数据转移
        Iterables.addAll(list, elements);
        return list;
    }
    

创建CopyOnWriteArrayList方法

  1. 不传入参数,直接返回一个新的CopyOnWriteArrayList

    public static  CopyOnWriteArrayList newCopyOnWriteArrayList() {
        return new CopyOnWriteArrayList();//直接返回一个新的CopyOnWriteArrayList
    }
    
  2. 传入一个容器,返回一个CopyOnWriteArrayList,带有传入容器的值

    public static  CopyOnWriteArrayList newCopyOnWriteArrayList(Iterable extends E> elements) {
        Object elementsCollection = elements instanceof Collection?Collections2.cast(elements):newArrayList((Iterable)elements);
        return new CopyOnWriteArrayList((Collection)elementsCollection);
    }
    

创建自制List规则

使用案例:

String leader = "leader";
String[] members = {"member1", "member2", "member3"};

List group = Lists.asList(leader, members);
System.out.println(group);

这样做的一个好处是可以提高代码的可读性,因为它明确地区分了 "leader" 和 "members",而不是将它们混在一起。而且,如果 "members" 是动态确定的(例如,它们来自另一个方法或计算结果),那么这个 asList 方法将比手动创建 List 并添加元素更为方便。

注意:asList返回的是视图,也就是说,原容器的变更会影响这些方法返回的容器内容

  1. 根据参数生成一个多一个参数的List

    public static  List asList(@Nullable E first, E[] rest) {
        return new Lists.OnePlusArrayList(first, rest);//返回一个Lists中的内部类OnePlusArrayList
    }
    
    private static class OnePlusArrayList extends AbstractList implements Serializable, RandomAccess {
        final E first;
        final E[] rest;
        private static final long serialVersionUID = 0L;
     
        OnePlusArrayList(@Nullable E first, E[] rest) {
            this.first = first;
            this.rest = (Object[])Preconditions.checkNotNull(rest);
        }
     
        // 重写了size和get方法
        // 因为是比原来数组多1个数,所以size方法在原来的基础上进行了+1操作。
        public int size() {
            return this.rest.length + 1;
        }
     
        //对get的重写是将所有的下标逻辑上后移了一位。
        public E get(int index) {
            Preconditions.checkElementIndex(index, this.size());
            return index == 0 ? this.first:this.rest[index - 1];
        }
    }
    
  2. 根据参数生成一个多两个个参数的List

    public static  List asList(@Nullable E first, @Nullable E second, E[] rest) {
        return new Lists.TwoPlusArrayList(first, second, rest);//返回一个Lists中的内部类TwoPlusArrayList
    }
    
    private static class TwoPlusArrayList extends AbstractList implements Serializable, RandomAccess {
        final E first;
        final E second;
        final E[] rest;
        private static final long serialVersionUID = 0L;
     
        TwoPlusArrayList(@Nullable E first, @Nullable E second, E[] rest) {
            this.first = first;
            this.second = second;
            this.rest = (Object[])Preconditions.checkNotNull(rest);
        }
     
        // 重写了size和get两个方法,size在实际数组长度上进行了+2的操作
        public int size() {
            return this.rest.length + 2;
        }
     
        //get则在逻辑上将下标进行了后移两位
        public E get(int index) {
            switch(index) {
            case 0:
                return this.first;
            case 1:
                return this.second;
            default:
                Preconditions.checkElementIndex(index, this.size());
                return this.rest[index - 2];
            }
        }
    } 
    

List笛卡尔乘积

public static  List> cartesianProduct(List extends List extends B>> lists) {
    return CartesianList.create(lists);
}

//整个方法的逻辑是将输入的一组列表转换成一个表示它们所有可能组合(笛卡尔积)的列表结构,同时确保输入列表的不可变性。
//这种方法在需要处理多维数据组合时特别有用,例如在配置管理、测试用例生成等应用场景中。
static  List> create(List extends List extends E>> lists) {
    ImmutableList.Builder> axesBuilder = new ImmutableList.Builder(lists.size());
    Iterator var2 = lists.iterator();

    while(var2.hasNext()) {
        List extends E> list = (List)var2.next();
        List copy = ImmutableList.copyOf(list);
        if (copy.isEmpty()) {
            //如果任意一个子列表为空,则整个笛卡尔积列表也应为空(因为任何东西与空集的笛卡尔积都是空集),因此直接返回一个空的不可变列表。
            return ImmutableList.of();
        }

        axesBuilder.add(copy);
    }

    return new CartesianList(axesBuilder.build());
}

List变形

使用案例:

List stringList = Arrays.asList("1", "2", "3");
List integerList = transform(stringList, s -> Integer.parseInt(s));

源码:

public static  List transform(List fromList, Function super F, ? extends T> function) {
    //依据 fromList 是否支持随机访问(例如 ArrayList),来决定使用哪种内部实现方式,以提高效率。
    //不过无论使用哪种方式进行处理,在他们的实现类中都重写了listIterator方法
    return (List)(fromList instanceof RandomAccess?new Lists.TransformingRandomAccessList(fromList, function):new Lists.TransformingSequentialList(fromList, function));
}


private static class TransformingRandomAccessList extends AbstractList implements RandomAccess, Serializable {
    final List fromList;
    final Function super F, ? extends T> function;
    private static final long serialVersionUID = 0L;
 
    TransformingRandomAccessList(List fromList, Function super F, ? extends T> function) {
        this.fromList = (List)Preconditions.checkNotNull(fromList);
        this.function = (Function)Preconditions.checkNotNull(function);
    }
    public ListIterator listIterator(int index) {
        //当通过 listIterator 方法获取迭代器时,实际上是获取了原始列表 fromList 的迭代器,并将其包装在 TransformedListIterator 中。
		//每次迭代时,TransformedListIterator 会调用 transform 方法,该方法使用 function 将原始列表中的元素转换为目标类型 T。
        return new TransformedListIterator(this.fromList.listIterator(index)) {
            T transform(F from) {
                return TransformingRandomAccessList.this.function.apply(from);
            }
        };
    }
}

分割list(作用之一:分页)

// 程序根据传入的List进行分类处理
public static  List> partition(List list, int size) {
    Preconditions.checkNotNull(list);
    Preconditions.checkArgument(size > 0);
    return (List)(list instanceof RandomAccess?new Lists.RandomAccessPartition(list, size):new Lists.Partition(list, size));
}

这里的RandomAccessPartition是Partition的子类,且RandomAccessPartition对其的处理是直接调用了父类的方法,所以我们只需要解析Partition类就可以了

private static class Partition extends AbstractList> {
    final List list;
    final int size;
    Partition(List list, int size) {
        this.list = list;
        this.size = size;
    }
    //get方法进行了截取操作,而它的截取底层是subList实现的。它所get的下标为第几组List
    public List get(int index) {
        Preconditions.checkElementIndex(index, this.size());
        int start = index * this.size;
        int end = Math.min(start + this.size, this.list.size());
        return this.list.subList(start, end);
    }
    public int size() {
        return IntMath.divide(this.list.size(), this.size, RoundingMode.CEILING);
    }
    public boolean isEmpty() {
        return this.list.isEmpty();
    }
}

将字符串作为字符数组进行操作

主要用于将一个字符串转换为一个不可变的 List,使得字符串的字符可以像列表元素一样进行操作。

//两个方法分别接收字符串和CharSequence作为参数,将参数传入CharSequenceAsList类中进行处理:
public static ImmutableList charactersOf(String string) {
    return new Lists.StringAsImmutableList((String)Preconditions.checkNotNull(string));
}
public static List charactersOf(CharSequence sequence) {
    return new Lists.CharSequenceAsList((CharSequence)Preconditions.checkNotNull(sequence));
}
//实际上就是对间接使用String类中的方法进行处理字符串
private static final class StringAsImmutableList extends ImmutableList {
    private final String string;
 
    StringAsImmutableList(String string) {
        this.string = string;
    }
 
    public int indexOf(@Nullable Object object) {
        return object instanceof Character?this.string.indexOf(((Character)object).charValue()):-1;
    }
 
    public int lastIndexOf(@Nullable Object object) {
        return object instanceof Character?this.string.lastIndexOf(((Character)object).charValue()):-1;
    }
 
    public ImmutableList subList(int fromIndex, int toIndex) {
        Preconditions.checkPositionIndexes(fromIndex, toIndex, this.size());
        return Lists.charactersOf((String)this.string.substring(fromIndex, toIndex));
    }
 
    boolean isPartialView() {
        return false;
    }
 
    public Character get(int index) {
        Preconditions.checkElementIndex(index, this.size());
        return Character.valueOf(this.string.charAt(index));
    }
 
    public int size() {
        return this.string.length();
    }
}

list逆序

public static  List reverse(List list) {
    if (list instanceof ImmutableList) {
        List> reversed = ((ImmutableList)list).reverse();
        List result = reversed;
        return result;
    } else if (list instanceof ReverseList) {
        return ((ReverseList)list).getForwardList();
    } else {
        return (List)(list instanceof RandomAccess ? new RandomAccessReverseList(list) : new ReverseList(list));
    }
}

实际上调用了ImmutableList类的reverse方法进行处理的逆序

Maps

private Maps() {
}

私有的构造方法,可以看到这是一个真正的功能函数,下面对其函数进行分析

功能函数

功能 方法
创建EnumMap 1、EnumMap newEnumMap(Class type)
2、EnumMap newEnumMap(Map map)
返回不可变EnumMap ImmutableMap immutableEnumMap(Map map)
创建HashMap 1、HashMap newHashMap()
2、HashMap newHashMapWithExpectedSize(int expectedSize)
3、HashMap newHashMap(Map extends K, ? extends V> map)
创建LinkedHashMap 1、LinkedHashMap newLinkedHashMap()
2、LinkedHashMap newLinkedHashMap(Map extends K, ? extends V> map)
创建ConcurrentMap ConcurrentMap newConcurrentMap()
创建TreeMap 1、TreeMap newTreeMap()
2、TreeMap newTreeMap(SortedMap map)
3、TreeMap newTreeMap(@Nullable Comparator comparator)
创建IdentityHashMap IdentityHashMap newIdentityHashMap()
获取两个Map中不同元素的值 1、MapDifference difference(Map extends K, ? extends V> left, Map extends K, ? extends V> right)
2、MapDifference difference(Map extends K, ? extends V> left, Map extends K, ? extends V> right, Equivalence super V> valueEquivalence)
3、SortedMapDifference difference(SortedMap left, Map extends K, ? extends V> right)
根据函数和set,构造Map 1、Map asMap(Set set, Function super K, V> function)
2、SortedMap asMap(SortedSet set, Function super K, V> function)
3、NavigableMap asMap(NavigableSet set, Function super K, V> function)
根据函数和迭代器,构造不可变的Map 1、ImmutableMap toMap(Iterator keys, Function super K, V> valueFunction)
2、ImmutableMap toMap(Iterator keys, Function super K, V> valueFunction)
3、ImmutableMap uniqueIndex(Iterable values, Function super V, K> keyFunction)
4、ImmutableMap uniqueIndex(Iterator values, Function super V, K> keyFunction)
从配置文件中读取数据,创建不可变的Map ImmutableMap fromProperties(Properties properties)
返回Entry或Entry集合 1、Entry immutableEntry(@Nullable K key, @Nullable V value)
2、Set> unmodifiableEntrySet(Set> entrySet)
3、Entry unmodifiableEntry(final Entry extends K, ? extends V> entry)
返回特殊的BiMap类 1、BiMap synchronizedBiMap(BiMap bimap)
2、BiMap unmodifiableBiMap(BiMap extends K, ? extends V> bimap)
根据Map和函数对Map进行转型 1、Map transformValues(Map fromMap, Function super V1, V2> function)
2、SortedMap transformValues(SortedMap fromMap, Function super V1, V2> function)
3、NavigableMap transformValues(NavigableMap fromMap, Function super V1, V2> function)
4、Map transformEntries(Map fromMap, Maps.EntryTransformer super K, ? super V1, V2> transformer)
5、SortedMap transformEntries(SortedMap fromMap, Maps.EntryTransformer super K, ? super V1, V2> transformer)
6、NavigableMap transformEntries(NavigableMap fromMap, Maps.EntryTransformer super K, ? super V1, V2> transformer)
使用函数进行过滤Map,然后返回同类型的Map 分为4种过滤
一、针对Key进行过滤
1.Map filterKeys(Map unfiltered, Predicate super K> keyPredicate)
2.SortedMap filterKeys(SortedMap unfiltered, Predicate super K> keyPredicate)
3.NavigableMap filterKeys(NavigableMap unfiltered, Predicate super K> keyPredicate)
4.BiMap filterKeys(BiMap unfiltered, Predicate super K> keyPredicate)
二、针对Value进行过滤
1.Map filterValues(Map unfiltered, Predicate super V> valuePredicate)
2.SortedMap filterValues(SortedMap unfiltered, Predicate super V> valuePredicate)
3.NavigableMap filterValues(NavigableMap unfiltered, Predicate super V> valuePredicate)
4.BiMap filterValues(BiMap unfiltered, Predicate super V> valuePredicate)
三、针对Entry进行过滤
1.Map filterEntries(Map unfiltered, Predicate super Entry> entryPredicate)
2.SortedMap filterEntries(SortedMap unfiltered, Predicate super Entry> entryPredicate)
3.SortedMap filterSortedIgnoreNavigable(SortedMap unfiltered, Predicate super Entry> entryPredicate)
4.NavigableMap filterEntries(NavigableMap unfiltered, Predicate super Entry> entryPredicate)
5.BiMap filterEntries(BiMap unfiltered, Predicate super Entry> entryPredicate)
四、为含有过滤规则的Map进行过滤
1.Map filterFiltered(Maps.AbstractFilteredMap map, Predicate super Entry> entryPredicate)
2.SortedMap filterFiltered(Maps.FilteredEntrySortedMap map, Predicate super Entry> entryPredicate)
3.NavigableMap filterFiltered(Maps.FilteredEntryNavigableMap map, Predicate super Entry> entryPredicate)
4.BiMap filterFiltered(Maps.FilteredEntryBiMap map, Predicate super Entry> entryPredicate)

创建EnumMap

  1. 传入一个Class变量,返回一个EnumMap

    public static , V> EnumMap newEnumMap(Class type) {
        return new EnumMap((Class)Preconditions.checkNotNull(type));
    }
    
  2. 传入一个Map变量,返回一个EnumMap

    public static , V> EnumMap newEnumMap(Map map) {
        return new EnumMap(map);
    }
    
    //java.util.EnumMap#EnumMap(java.util.Map)
    public EnumMap(Map m) {
        if (m instanceof EnumMap) {
            EnumMap em = (EnumMap) m;
            keyType = em.keyType;
            keyUniverse = em.keyUniverse;
            vals = em.vals.clone();
            size = em.size;
        } else {
            if (m.isEmpty())
                throw new IllegalArgumentException("Specified map is empty");
            keyType = m.keySet().iterator().next().getDeclaringClass();
            keyUniverse = getKeyUniverse(keyType);
            vals = new Object[keyUniverse.length];
            //对于传入的Map赋值给新的EnumMap步骤就由EnumMap的putAll方法进行操作了。
            putAll(m);
        }
    }
    

返回不可变EnumMap

传入一个Map,返回一个不可变的Map容器

public static , V> ImmutableMap immutableEnumMap(Map map) {
    if(map instanceof ImmutableEnumMap) {
        //如果map为ImmutableEnumMap类型,直接强转为ImmutableEnumMap类型的容器
        ImmutableEnumMap result = (ImmutableEnumMap)map;
        return result;
    } else  {
        Iterator extends Map.Entry> entryItr = map.entrySet().iterator();
        if (!entryItr.hasNext()) {
            //如果map为空,则直接返回新建的空的ImmutableMap容器
            return ImmutableMap.of();
        } else {
            Map.Entry entry1 = (Map.Entry)entryItr.next();
            K key1 = (Enum)entry1.getKey();
            V value1 = entry1.getValue();
            CollectPreconditions.checkEntryNotNull(key1, value1);
            Class clazz = key1.getDeclaringClass();
            EnumMap enumMap = new EnumMap(clazz);
            enumMap.put(key1, value1);

            while(entryItr.hasNext()) {
                Map.Entry entry = (Map.Entry)entryItr.next();
                K key = (Enum)entry.getKey();
                V value = entry.getValue();
                //key和value都不能为null
                CollectPreconditions.checkEntryNotNull(key, value);
                enumMap.put(key, value);
            }
			
            //以上成立,则直接使用ImmutableEnumMap中函数为map进行转换
            return ImmutableEnumMap.asImmutable(enumMap);
        }
    }
}

创建HashMap

  1. 直接返回一个新的HashMap

    public static  HashMap newHashMap() {
        return new HashMap();
    }
    
  2. 返回一个有初始长度的HashMap

    public static  HashMap newHashMapWithExpectedSize(int expectedSize) {
        return new HashMap(capacity(expectedSize));
    }
    
    //根据传入的长度,返回一个实际可用expectedSize的HashMap,capacity方法就是计算实际长度的一个方法
    static int capacity(int expectedSize) {
        if(expectedSize 

    这里为什么是 0.75这个系数呢?

  3. 传入一个Map型变量,返回一个HashMap

    public static  HashMap newHashMap(Map extends K, ? extends V> map) {
        return new HashMap(map);//这个步骤就由HashMap的putMapEntries方法进行操作了
    }
    

创建LinkedHashMap

  1. 直接返回一个新的LinkedHashMap

    public static  LinkedHashMap newLinkedHashMap() {
        return new LinkedHashMap();
    }
    
  2. 传入一个Map变量,返回一个LinkedHashMap

    public static  LinkedHashMap newLinkedHashMap(Map extends K, ? extends V> map) {
        return new LinkedHashMap(map);//这个步骤就由LinkedHashMap的putMapEntries方法进行操作了。
    }
    

创建ConcurrentMap

直接返回一个新的ConcurrentMap

public static  ConcurrentMap newConcurrentMap() {
    return new ConcurrentHashMap();
}

创建TreeMap

  1. 直接返回一个新的TreeMap

    public static  TreeMap newTreeMap() {
        return new TreeMap();
    }
    
  2. 传入一个Map变量,返回一个TreeMap,并将Map的值赋值给TreeMap

    public static  TreeMap newTreeMap(SortedMap map) {
        return new TreeMap(map);
    }
    
  3. 传入一个比较接口,返回一个根据传入的比较规则形成的TreeMap

    public static  TreeMap newTreeMap(@Nullable Comparator comparator) {
        return new TreeMap(comparator);
    }
    

创建IdentityHashMap

直接返回一个identityHashMap

public static  IdentityHashMap newIdentityHashMap() {
    return new IdentityHashMap();
}

IdentityHashMap与HashMap不同之处在于可以存入相同类的相同值,实际上他在put里的添加操作是不是使用equals而是用的==进行判断的

获取两个Map中不同元素的值

在说明Maps中这三个方法之前,先了解一下MapDifference接口和的实现类MapDifferenceImpl可以表现什么吧:

public interface MapDifference {
    boolean areEqual();
    Map entriesOnlyOnLeft();
    Map entriesOnlyOnRight();
    Map entriesInCommon();
    Map> entriesDiffering();
    boolean equals(@CheckForNull Object var1);
    int hashCode();

    @DoNotMock("Use Maps.difference")
    public interface ValueDifference {
        @ParametricNullness
        V leftValue();
        @ParametricNullness
        V rightValue();
        
        boolean equals(@CheckForNull Object var1);
        int hashCode();
    }
}

static class MapDifferenceImpl implements MapDifference {
    final Map onlyOnLeft;
    final Map onlyOnRight;
    final Map onBoth;
    final Map> differences;
 
    MapDifferenceImpl(Map onlyOnLeft, Map onlyOnRight, Map onBoth, Map> differences) {
        this.onlyOnLeft = Maps.unmodifiableMap(onlyOnLeft);
        this.onlyOnRight = Maps.unmodifiableMap(onlyOnRight);
        this.onBoth = Maps.unmodifiableMap(onBoth);
        this.differences = Maps.unmodifiableMap(differences);
    }
    
    public boolean areEqual() {
        return this.onlyOnLeft.isEmpty() && this.onlyOnRight.isEmpty() && this.differences.isEmpty();
    }
    public Map entriesOnlyOnLeft() {return this.onlyOnLeft; }
    public Map entriesOnlyOnRight() {return this.onlyOnRight; }
    public Map entriesInCommon() {return this.onBoth; }
    public Map> entriesDiffering() { return this.differences; }
    
    //equals等其它方法...
}

可以看到 MapDifferenceImpl 实现类中有4个变量

  • onlyOnLeft只存变量名为left的Map中独有的;
  • onlyOnRight只存变量名为right的Map中独有的;
  • onBoth存储两个map中共有的key并且value也相等的元素;
  • differences因为value存储的类型为ValueDifference,differences中存储的是共有的key并且value不同的元素
  1. 传入两个Map变量,根据left变量名的Map的类型进行判断交给哪个difference方法去处理

    public static  MapDifference difference(Map extends K, ? extends V> left, Map extends K, ? extends V> right) {
        if(left instanceof SortedMap) {
            SortedMap sortedLeft = (SortedMap)left;
            return difference(sortedLeft, right);
        } else {
            MapDifference result = difference(left, right, Equivalence.equals());
            return result;
        }
    }
    
  2. 传入两个Map,使用doDifference方法将两个Map中的元素进行分类

    public static  MapDifference difference(Map extends K, ? extends V> left, Map extends K, ? extends V> right, Equivalence super V> valueEquivalence) {
        Preconditions.checkNotNull(valueEquivalence);
        HashMap onlyOnLeft = newHashMap();
        HashMap onlyOnRight = new HashMap(right);
        HashMap onBoth = newHashMap();
        Map> differences = newLinkedHashMap();
        doDifference(left, right, valueEquivalence, onlyOnLeft, onlyOnRight, onBoth, differences);
        return new Maps.MapDifferenceImpl(onlyOnLeft, onlyOnRight, onBoth, differences);
    }
    
    private static  void doDifference(Map extends K, ? extends V> left, Map extends K, ? extends V> right, Equivalence super V> valueEquivalence, Map onlyOnLeft, Map onlyOnRight, Map onBoth, Map> differences) {
        Iterator var7 = left.entrySet().iterator();
    
        //对left进行遍历操作
        while(var7.hasNext()) {
            Map.Entry extends K, ? extends V> entry = (Map.Entry)var7.next();
            K leftKey = entry.getKey();
            V leftValue = entry.getValue();
            //查看right中是否包括这个key值
            if (right.containsKey(leftKey)) {
                //如果right中也包括这个key值,则将这个值在right中去除
                V rightValue = NullnessCasts.uncheckedCastNullableTToT(onlyOnRight.remove(leftKey));
                //判断这个key值的left和right的value值是否相等
                if (valueEquivalence.equivalent(leftValue, rightValue)) {
                    //如果两个value值相等,将其填入onBoth的Map容器中
                    onBoth.put(leftKey, leftValue);
                } else {
                    //如果两个value值不相等,将其填入differences的Map容器中
                    differences.put(leftKey, Maps.ValueDifferenceImpl.create(leftValue, rightValue));
                }
            } else {
                //如果这个key在right中不存在,则将其填入onlyOnLeft容器中
                onlyOnLeft.put(leftKey, leftValue);
            }
        }
    }
    
  3. 传入一个SortedMap和一个Map变量,返回一个分类后的类

    public static  SortedMapDifference difference(SortedMap left, Map extends K, ? extends V> right) {
        Preconditions.checkNotNull(left);
        Preconditions.checkNotNull(right);
        Comparator super K> comparator = orNaturalOrder(left.comparator());
        SortedMap onlyOnLeft = newTreeMap(comparator);
        SortedMap onlyOnRight = newTreeMap(comparator);
        onlyOnRight.putAll(right);
        SortedMap onBoth = newTreeMap(comparator);
        SortedMap> differences = newTreeMap(comparator);
        doDifference(left, right, Equivalence.equals(), onlyOnLeft, onlyOnRight, onBoth, differences);
        return new SortedMapDifferenceImpl(onlyOnLeft, onlyOnRight, onBoth, differences);
    }
    

根据函数和set,构造Map

这个方法展示了如何将一个Set和一个Function 结合起来,创建一个视图(view),这个视图在每次查询时通过应用函数来动态生成键值对。

  1. 视图特性AsMapView创建的是一个视图,而不是一个独立的新集合。这意味着原始集合(Set)的任何修改都会反映在AsMapView中,反之亦然。这种行为类似于如何通过Collections.unmodifiableList()方法得到的不可修改的视图,但AsMapView是可修改的,其修改会影响到原始的集合。
  2. 延迟加载AsMapView在实际调用其get()方法之前不会计算键对应的值。这意味着如果你有一个非常昂贵的转换逻辑,它只有在实际需要该值时才会执行,这有助于提高效率。
  3. 用途:这个类非常适合创建动态计算的映射,其中映射的值是依赖于键的,并且可能不希望提前计算所有可能的值。例如,可以用它来根据需要生成配置设置、进行数据转换等。
  4. 实现:在内部,AsMapView使用了提供的SetFunction来实现Map接口。当调用get(Object key)时,如果key存在于集合中,则使用Function来计算值。

使用案例:

//假设有一组产品ID,需要根据产品ID动态获取产品价格。价格计算可能依赖于多种因素,如商品的实时供需状况、促销活动等,这些都可以通过一个函数来实现:
Set productIds = new HashSet();
productIds.add(1);
productIds.add(2);

Function priceFunction = productId -> {
    // 假设这里进行一些复杂的计算来决定价格
    return productId * 10.0; // 简单的示例
};

Map priceMap = Maps.asMap(productIds, priceFunction);

System.out.println("Price of Product 1: " + priceMap.get(1));  // 输出 10.0
System.out.println("Price of Product 2: " + priceMap.get(2));  // 输出 20.0

方法介绍:

  1. 传入一个set和一个规则,返回一个Map

    public static  Map asMap(Set set, Function super K, V> function) {
        return new AsMapView(set, function);
    }
    
  2. 传入一个SortedSet和一个规则,返回一个SortMap

    public static  SortedMap asMap(SortedSet set, Function super K, V> function) {
        return new SortedAsMapView(set, function);
    }
    
  3. 传入一个NavigableSet和一个规则,返回一个NavigableMap

    public static  NavigableMap asMap(NavigableSet set, Function super K, V> function) {
        return new Maps.NavigableAsMapView(set, function);
    }
    

根据函数和迭代器,构造不可变的Map

此类方法传入的是一个容器的迭代器和一个规则,然后返回一个不可变的Map容器

  1. 传入一个key值容器和一个规则,直接交给重载函数去处理,返回一个不可变的Map容器

    public static  ImmutableMap toMap(Iterable keys, Function super K, V> valueFunction) {
        return toMap((Iterator)keys.iterator(), valueFunction);
    }
    
    
  2. 传入一个key值迭代器和一个规则返回一个不可变的map容器

    public static  ImmutableMap toMap(Iterator keys, Function super K, V> valueFunction) {
        Preconditions.checkNotNull(valueFunction);
        LinkedHashMap builder = newLinkedHashMap();
        //使用迭代器中的值作为key值,使用规则计算出的值作为value值,存入builder中
        while(keys.hasNext()) {
            Object key = keys.next();
            builder.put(key, valueFunction.apply(key));
        }
        //返回一个不可变的容器
        return ImmutableMap.copyOf(builder);
    }
    
  3. 根据value值容器和一个规则,直接交给重载函数去处理,返回一个不可变的Map容器

    public static  ImmutableMap uniqueIndex(Iterable values, Function super V, K> keyFunction) {
        return uniqueIndex((Iterator)values.iterator(), keyFunction);
    }
    
  4. 传入一个value值迭代器和一个规则返回一个不可变的map容器

    public static  ImmutableMap uniqueIndex(Iterator values, Function super V, K> keyFunction) {
        Preconditions.checkNotNull(keyFunction);
        Builder builder = ImmutableMap.builder();
        //使用迭代器中的值作为value值,使用规则计算出的值作为key值,存入builder中
        while(values.hasNext()) {
            Object value = values.next();
            builder.put(keyFunction.apply(value), value);
        }
        //返回一个不可变的容器
        return builder.build();
    }
    

从properties文件中读取数据,创建不可变的Map

从Properties获取的key和value,返回一个不可变的Map

public static ImmutableMap fromProperties(Properties properties) {
    Builder builder = ImmutableMap.builder();
    Enumeration e = properties.propertyNames();
    //从properties获取的key和value,赋值到builder中
    while(e.hasMoreElements()) {
        String key = (String)e.nextElement();
        builder.put(key, properties.getProperty(key));
    }
    //返回一个不可变的Map
    return builder.build();
}

返回Entry或Entry集合

传入一个key和一个value,返回一个不可变的Entry

public static  Entry immutableEntry(@Nullable K key, @Nullable V value) {
    return new ImmutableEntry(key, value);
}

返回特殊的BiMap类

Guava 提供了 BiMap 支持支持双向的映射关系,关于BiMap详情可以看后文

  1. 传入一个BiMap返回一个线程安全的BiMap

    public static  BiMap synchronizedBiMap(BiMap bimap) {
        return Synchronized.biMap(bimap, (Object)null);
    }
    
  2. 传入一个BiMap返回一个unmodifiableBiMap

    public static  BiMap unmodifiableBiMap(BiMap extends K, ? extends V> bimap) {
        return new Maps.UnmodifiableBiMap(bimap, (BiMap)null);
    }
    

根据Map和函数对Map进行转型

此类方法使用使用到了函数式编程,将一个Map的value作为新的Map的key,根据函数的规则计算出新的Map的Value,而这个转换只有在查看的时候才会做计算,而真正存储的是传入的map

  1. 传入一个Map和一个规则,返回一个有规则计算出来的Map

    public static  Map transformValues(Map fromMap, Function super V1, V2> function) {
        return transformEntries((Map)fromMap, asEntryTransformer(function));
    }
    
  2. 传入一个SortedMap和一个规则,返回一个由规则计算出来的新的Map

    public static  SortedMap transformValues(SortedMap fromMap, Function super V1, V2> function) {
        return transformEntries((SortedMap)fromMap, asEntryTransformer(function));
    }
    
  3. 传入一个NavigableMap和一个规则,返回一个由规则计算出来的NavigableMap

    public static  NavigableMap transformValues(NavigableMap fromMap, Function super V1, V2> function) {
        return transformEntries((NavigableMap)fromMap, asEntryTransformer(function));
    }
    
  4. 传入一个Map和一个Maps规定的规则格式,根据规则返回一个新的Map

    public static  Map transformEntries(Map fromMap, Maps.EntryTransformer super K, ? super V1, V2> transformer) {
        return (Map)(fromMap instanceof SortedMap?transformEntries((SortedMap)((SortedMap)fromMap), transformer):new Maps.TransformedEntriesMap(fromMap, transformer));
    }
    
  5. 传入一个NavigableMap和一个Maps规定的规则格式,根据规则返回一个新的NavigableMap

    public static  NavigableMap transformEntries(NavigableMap fromMap, Maps.EntryTransformer super K, ? super V1, V2> transformer) {
        return new Maps.TransformedEntriesNavigableMap(fromMap, transformer);
    }
    

使用函数进行过滤Map,然后返回同类型的Map

这里我们主要针对Key进行过滤的源码进行分析。当然Maps还提供了一些对Value、Entry、含有过滤器的Map进行过滤的方法。与上面过滤key的方法大体一样,都是继承了AbstractFilteredMap抽象类,实现了各自的过滤功能

使用keyPredicate函数接口制定过滤规则,对Map进行过滤,对于Map中Key进行过滤的类FilteredKeyMap源码如下:

// 对KeySet进行了过滤处理,使用了Set中的filter方法
private static class FilteredKeyMap extends Maps.AbstractFilteredMap {
    Predicate super K> keyPredicate;
    FilteredKeyMap(Map unfiltered, Predicate super K> keyPredicate, Predicate super Entry> entryPredicate) {
        super(unfiltered, entryPredicate);
        this.keyPredicate = keyPredicate;
    }
    protected Set> createEntrySet() {
        return Sets.filter(this.unfiltered.entrySet(), this.predicate);
    }
 
    Set createKeySet() {
        return Sets.filter(this.unfiltered.keySet(), this.keyPredicate);
    }
 
    public boolean containsKey(Object key) {
        return this.unfiltered.containsKey(key) && this.keyPredicate.apply(key);
    }
}
  1. 传入一个Map和过滤他的规则,返回一个新的Map

    public static  Map filterKeys(Map unfiltered, Predicate super K> keyPredicate) {
            Preconditions.checkNotNull(keyPredicate);
            Predicate> entryPredicate = keyPredicateOnEntries(keyPredicate);
            return (Map)(unfiltered instanceof AbstractFilteredMap ? filterFiltered((AbstractFilteredMap)unfiltered, entryPredicate) : new FilteredKeyMap((Map)Preconditions.checkNotNull(unfiltered), keyPredicate, entryPredicate));
        }
    
  2. 传入一个SortedMap,然后交给filterEntries方法进行处理

    public static  SortedMap filterKeys(SortedMap unfiltered, Predicate super K> keyPredicate) {
        return filterEntries(unfiltered, keyPredicateOnEntries(keyPredicate));
    }
    
  3. 传入一个NavigableMap,然后交给filterEntries方法进行处理

    public static  NavigableMap filterKeys(NavigableMap unfiltered, Predicate super K> keyPredicate) {
        return filterEntries((NavigableMap)unfiltered, keyPredicateOnEntries(keyPredicate));
    }
    
  4. 传入一个BiMap,然后交给filterEntries方法进行处理

    public static  BiMap filterKeys(BiMap unfiltered, Predicate super K> keyPredicate) {
        Preconditions.checkNotNull(keyPredicate);
        return filterEntries((BiMap)unfiltered, keyPredicateOnEntries(keyPredicate));
    }
    

Sets

功能函数

功能 方法
创建不可变的set 1、ImmutableSet immutableEnumSet(E anElement, E... otherElements)
2、ImmutableSet immutableEnumSet(Iterable elements)
创建HashSet 1、HashSet newHashSet()
2、HashSet newHashSet(E... elements)
3、HashSet newHashSetWithExpectedSize(int expectedSize)
4、HashSet newHashSet(Iterable extends E> elements)
5、HashSet newHashSet(Iterator extends E> elements)
创建线程安全的Set 1、Set newConcurrentHashSet()
2、Set newConcurrentHashSet(Iterable extends E> elements)
创建LinkedHashMap 1、LinkedHashSet newLinkedHashSet()
2、LinkedHashSet newLinkedHashSetWithExpectedSize(int expectedSize)
3、LinkedHashSet newLinkedHashSet(Iterable extends E> elements)
创建TreeSet 1、TreeSet newTreeSet()
2、TreeSet newTreeSet(Iterable extends E> elements)
3、TreeSet newTreeSet(Comparator super E> comparator)
创建IdentityHashSet Set newIdentityHashSet()
创建CopyOnWriteArraySet 1、CopyOnWriteArraySet newCopyOnWriteArraySet()
2、CopyOnWriteArraySet newCopyOnWriteArraySet(Iterable extends E> elements)
创建EnumSet 1、EnumSet newEnumSet(Iterable iterable, Class elementType)
2、EnumSet complementOf(Collection collection)
3、EnumSet complementOf(Collection collection, Class type)
4、EnumSet makeComplementByHand(Collection collection, Class type)
根据Map创建一个Set Set newSetFromMap(Map map)
以两个Set的并集作为视图 Sets.SetView union(final Set extends E> set1, final Set extends E> set2)
以两个Set的交集作为视图 Sets.SetView intersection(final Set set1, final Set> set2)
以两个Set的互不重叠的部分作为视图 Sets.SetView difference(final Set set1, final Set> set2)
以两个Set的对称部分作为视图 Sets.SetView symmetricDifference(Set extends E> set1, Set extends E> set2)
过滤Set 1、filter(Set unfiltered, Predicate super E> predicate)
2、SortedSet filter(SortedSet unfiltered, Predicate super E> predicate)
3、SortedSet filterSortedIgnoreNavigable(SortedSet unfiltered, Predicate super E> predicate)
4、NavigableSet filter(NavigableSet unfiltered, Predicate super E> predicate)
获取两个Set集合的笛卡尔积 1、Set> cartesianProduct(List extends Set extends B>> sets)
2、Set> cartesianProduct(Set extends B>... sets)

创建不可变的Set

  1. 根据传入的参数,创建一个不可变的Set

    public static > ImmutableSet immutableEnumSet(E anElement, E... otherElements) {
        //使用ImmutableEnumSet.asImmutable函数将EnumSet转为ImmutableSet
        return ImmutableEnumSet.asImmutable(EnumSet.of(anElement, otherElements));
    }
    
    //EnumSet.of方法是将anElement和otherElements合并成一个EnumSet
    public static > EnumSet of(E first, E... rest) {
        EnumSet result = noneOf(first.getDeclaringClass());
        //将第一个参数先插入到EnumSet中
        result.add(first);
        //在将传入的数组全部插入到EnumSet中
        for (E e : rest)
            result.add(e);
        return result;
    }
    
  2. 根据一个集合创建一个不可变的Set

    public static > ImmutableSet immutableEnumSet(Iterable elements) {
        //如果是一个ImmutableEnumSet,则直接转换为ImmutableEnumSet
        if(elements instanceof ImmutableEnumSet) {
            return (ImmutableEnumSet)elements;
        } else if(elements instanceof Collection) {
            //如果是一个Collection且不为空则,直接使用ImmutableEnumSet.asImmutable方法转化为ImmutableEnumSet
            Collection itr1 = (Collection)elements;
            return itr1.isEmpty()?ImmutableSet.of():ImmutableEnumSet.asImmutable(EnumSet.copyOf(itr1));
        } else {
            //其他类型,则获取他的迭代器,然后制作一个ImmutableEnumSet
            Iterator itr = elements.iterator();
            if(itr.hasNext()) {
                EnumSet enumSet = EnumSet.of((Enum)itr.next());
                Iterators.addAll(enumSet, itr);
                return ImmutableEnumSet.asImmutable(enumSet);
            } else {
                return ImmutableSet.of();
            }
        }
    }
    

创建HashSet

  1. 直接new一个HashSet

    public static  HashSet newHashSet() {
        return new HashSet();
    }
    
  2. 传入一个数组,返回一个HashSet

    public static  HashSet newHashSet(E... elements) {
        //创建一个期望大小为elements.length的HashSet
        HashSet set = newHashSetWithExpectedSize(elements.length);
        //将数组中的元素,全部赋值给新的HashSet
        Collections.addAll(set, elements);
        return set;
    }
    
  3. 创建一个期望大小的HashSet

    public static  HashSet newHashSetWithExpectedSize(int expectedSize) {
        //创建一个HashSet,大小为Maps.capacity方法计算后的值,这个方法最终返回原值的4/3
        return new HashSet(Maps.capacity(expectedSize));
    }
    
  4. 根据传入的集合创建一个HashSet

    public static  HashSet newHashSet(Iterable extends E> elements) {
        return elements instanceof Collection?new HashSet(Collections2.cast(elements)):newHashSet((Iterator)elements.iterator());
    }
    
  5. 根据传入的迭代器创建一个HashSet

    public static  HashSet newHashSet(Iterator extends E> elements) {
        //创建一个HashSet
        HashSet set = newHashSet();
        //使用Guava中的Iterators.addAll方法将迭代器中的元素添加到set中
        Iterators.addAll(set, elements);
        return set;
    }
    

创建线程安全的Set

  1. 使用ConcurrentHashMap创建一个Set

    public static  Set newConcurrentHashSet() {
        //创建一个ConcurrentHashMap,使用newSetFromMap方法将ConcurrentHashMap的值转为Set
        return newSetFromMap(new ConcurrentHashMap());
    }
    
  2. 使用传入的集合创建一个线程安全的Set

    public static  Set newConcurrentHashSet(Iterable extends E> elements) {
        //创建一个ConcurrentHashSet
        Set set = newConcurrentHashSet();
        //使用Guava中的Iterables.addAll方法将集合elements中的元素添加到set中
        Iterables.addAll(set, elements);
        return set;
    }
    

创建LinkedHashSet

  1. 直接创建一个LinkedHashSet

    public static  LinkedHashSet newLinkedHashSet() {
        return new LinkedHashSet();
    }
    
  2. 创建一个期望大小的LinkedHashSet

    public static  LinkedHashSet newLinkedHashSetWithExpectedSize(int expectedSize) {
        //返回一个LinkedHashSet,大小为expectedSize的4/3
        return new LinkedHashSet(Maps.capacity(expectedSize));
    }
    
  3. 根据传入的集合,返回一个LinkedHashSet

    public static  LinkedHashSet newLinkedHashSet(Iterable extends E> elements) {
        //如果是一个Collection类型,则直接创建LinkedHashSet,并将集合中的值赋值给新的LinkedHashSet
        if(elements instanceof Collection) {
            return new LinkedHashSet(Collections2.cast(elements));
        } else {
            LinkedHashSet set = newLinkedHashSet();
            Iterables.addAll(set, elements);
            return set;
        }
    }
    
    
    
    

创建TreeSet

  1. 直接创建一个TreeSet

    public static  TreeSet newTreeSet() {
        return new TreeSet();
    }
    
  2. 传入一个集合,返回一个TreeSet,并将集合中的元素赋值给TreeSet

    public static  TreeSet newTreeSet(Iterable extends E> elements) {
        //创建一个TreeSet
        TreeSet set = newTreeSet();
        //将集合中的元素赋值给TreeSet
        Iterables.addAll(set, elements);
        return set;
    }
    
  3. 传入一个Comparator,根据Comparator的规则创建一个TreeSet

    public static  TreeSet newTreeSet(Comparator super E> comparator) {
        return new TreeSet((Comparator)Preconditions.checkNotNull(comparator));
    }
    

创建IdentityHashSet

根据Maps.newIdentityHashMap()和Sets.newSetFromMap两个方法创建一个IdentityHashSet

public static  Set newIdentityHashSet() {
    //使用Maps.newIdentityHashMap()方法创建一个IdentityHashMap,然后使用newSetFromMap方法将Map转为Set
    return newSetFromMap(Maps.newIdentityHashMap());
}

创建CopyOnWriteArraySet

  1. 直接创建一个CopyOnWriteArraySet

    public static  CopyOnWriteArraySet newCopyOnWriteArraySet() {
        return new CopyOnWriteArraySet();
    }
    
  2. 根据传入的集合创建一个CopyOnWriteArraySet,并将集合中的数据赋值给CopyOnWriteArraySet

    public static  CopyOnWriteArraySet newCopyOnWriteArraySet(Iterable extends E> elements) {
        //如果是一个Collection,直接将其转为Collection,如果不是则使用Lists创建一个List
        Object elementsCollection = elements instanceof Collection?Collections2.cast(elements):Lists.newArrayList(elements);
        return new CopyOnWriteArraySet((Collection)elementsCollection);
    }
    

创建EnumSet

  1. 根据传入的集合和一个类型,返回一个EnumSet

    public static > EnumSet newEnumSet(Iterable iterable, Class elementType) {
        //根据传入的类型,创建一个set
        EnumSet set = EnumSet.noneOf(elementType);
        //将集合中的元素添加到set中
        Iterables.addAll(set, iterable);
        return set;
    }
    
  2. 传入一个集合,返回一个EnumSet

    public static > EnumSet complementOf(Collection collection) {
        if(collection instanceof EnumSet) {
            return EnumSet.complementOf((EnumSet)collection);
        } else {
            Preconditions.checkArgument(!collection.isEmpty(), "collection is empty; use the other version of this method");
            Class type = ((Enum)collection.iterator().next()).getDeclaringClass();
            return makeComplementByHand(collection, type);
        }
    }
    

根据一个Map创建一个Set

根据Map创建一个Set

public static  Set newSetFromMap(Map map) {
    return Platform.newSetFromMap(map);
}
//Platform.newSetFromMap方法,一层一层往上追,最终可以看到,实际上使用的是Collections.SetFromMap类:

private static class SetFromMap extends AbstractSet implements Set, Serializable{
    private final Map m;  // The backing map
    private transient Set s;       // Its keySet
    SetFromMap(Map map) {//其实就是将map中的key集合作为一个Set了
        if (!map.isEmpty())
            throw new IllegalArgumentException("Map is non-empty");
        m = map;
        s = map.keySet();
    }
}

以两个Set的互不重叠的部分作为视图

传入两个Set,返回一个两个set1中不包含set2中的元素

public static  Sets.SetView difference(final Set set1, final Set> set2) {
    Preconditions.checkNotNull(set1, "set1");
    Preconditions.checkNotNull(set2, "set2");
    //创建一个过滤规则(规则为,不能包含set2中的元素)
    final Predicate notInSet2 = Predicates.not(Predicates.in(set2));
    return new Sets.SetView(null) {
        //重写iterator,使用Iterators.filter过滤出不含set2元素的一个迭代器
        public Iterator iterator() {
            return Iterators.filter(set1.iterator(), notInSet2);
        }
        //根据最终返回的迭代器计算长度
        public int size() {
            return Iterators.size(this.iterator());
        }
        //如果set1和set2中全部相等,就为空
        public boolean isEmpty() {
            return set2.containsAll(set1);
        }
        public boolean contains(Object element) {
            return set1.contains(element) && !set2.contains(element);
        }
    };
}

以两个Set的并集作为视图

public static  Sets.SetView union(final Set extends E> set1, final Set extends E> set2) {
    Preconditions.checkNotNull(set1, "set1");
    Preconditions.checkNotNull(set2, "set2");
    //获取set2,中不包含set1的所有元素
    final Sets.SetView set2minus1 = difference(set2, set1);
    return new Sets.SetView(null) {
        //获取set1的全部长度和set2minus1视图的长度
        public int size() {
            return set1.size() + set2minus1.size();
        }
        public boolean isEmpty() {
            return set1.isEmpty() && set2.isEmpty();
        }
        public Iterator iterator() {
            return Iterators.unmodifiableIterator(Iterators.concat(set1.iterator(), set2minus1.iterator()));
        }
        public boolean contains(Object object) {
            return set1.contains(object) || set2.contains(object);
        }
        //返回所有元素
        public > S copyInto(S set) {
            set.addAll(set1);
            set.addAll(set2);
            return set;
        }
        public ImmutableSet immutableCopy() {
            return (new Builder()).addAll(set1).addAll(set2).build();
        }
    };
}

以两个Set的交集作为视图

public static  Sets.SetView intersection(final Set set1, final Set> set2) {
    Preconditions.checkNotNull(set1, "set1");
    Preconditions.checkNotNull(set2, "set2");
    //创建一个过滤规则(规则为:全部set2元素)
    final Predicate inSet2 = Predicates.in(set2);
    return new Sets.SetView(null) {
        //返回set1中包含set2中的所有元素
        public Iterator iterator() {
            return Iterators.filter(set1.iterator(), inSet2);
        }
        //根据计算出的迭代器计算长度
        public int size() {
            return Iterators.size(this.iterator());
        }
        //根据迭代器判断是否为空
        public boolean isEmpty() {
            return !this.iterator().hasNext();
        }
        public boolean contains(Object object) {
            return set1.contains(object) && set2.contains(object);
        }
        public boolean containsAll(Collection> collection) {
            return set1.containsAll(collection) && set2.containsAll(collection);
        }
    };
}

以两个Set的对称部分作为视图

public static  Sets.SetView symmetricDifference(Set extends E> set1, Set extends E> set2) {
    Preconditions.checkNotNull(set1, "set1");
    Preconditions.checkNotNull(set2, "set2");
    return difference(union(set1, set2), intersection(set1, set2));
}

过滤Set

Set的过滤和Maps中实现的各种过滤都是大同小异。

传入一个Set和一个过滤规则,返回一个过滤后的Set:

public static  Set filter(Set unfiltered, Predicate super E> predicate) {
    //如果传入的Set为SortedSet类型,使用传入SortedSet的方法进行处理
    if(unfiltered instanceof SortedSet) {
        return filter((SortedSet)((SortedSet)unfiltered), predicate);
    } else if(unfiltered instanceof Sets.FilteredSet) {
        Sets.FilteredSet filtered = (Sets.FilteredSet)unfiltered;
        Predicate combinedPredicate = Predicates.and(filtered.predicate, predicate);
        return new Sets.FilteredSet((Set)filtered.unfiltered, combinedPredicate);
    } else {
        return new Sets.FilteredSet((Set)Preconditions.checkNotNull(unfiltered), (Predicate)Preconditions.checkNotNull(predicate));
    }
}

往期推荐

本文来自在线网站:seven的菜鸟成长之路,作者:seven,转载请注明原文链接:www.seven97.top

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认