如《Effective Java》Item1)所述,在设计类的时候,倾向优先使用静态工厂方法(static factory method)而非构造函数(constructor)创建对象,优点在于:
同样,如《Effective Java》Item17所述,需要最小化可变性,ImmutableList
遵循了最佳实践。首先,ImmutableList
不可以通过构造函数实例化,更准确地说,不可以在package
外部通过构造函数实例化。
而在程序设计中使用不可变对象,也可以提高代码的可靠性和可维护性,其优势包括:
创建对象的不可变拷贝是一项很好的防御性编程技巧。Guava为所有JDK标准集合类型和Guava新集合类型都提供了简单易用的不可变版本。JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式.
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 提供的不可变集合不是原容器的视图,而是原容器的一份拷贝,因此更加简单高效,确保了真正的不可变性。
但是还要注意,由于immutable只是copy了元容器本身,并不是deep copy,因此对原容器的引用的内容进行修改,也会影响immutableXXX
注意:每个Guava immutable集合类的实现都拒绝null值。如果确实需要能接受null值的集合类,可以考虑用Collections.unmodifiableXXX。
immutable集合可以有以下几种方式来创建:
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]]
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 hugeList
, ImmutableList.copyOf(hugeList.subList(0, 10))
就会显式地拷贝(如上源码,会判断是否是局部视图),以免不必要地持有hugeList的引用。在可能的情况下避免线性拷贝,可以最大限度地减少防御性编程风格所带来的性能开销。
可变集合类型 | 可变集合源: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 |
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 |
分割list(作用之一:分页) | partition(List |
将字符串作为字符数组进行操作 | 1、charactersOf(String string) 2、charactersOf(CharSequence sequence) |
将list逆序 | reverse(List |
没有参数的创建ArrayList
public static ArrayList newArrayList() {
return new ArrayList();//直接返回一个新的ArrayList容器
}
传入一个数组,返回一个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));
}
传入一个集合顶级接口,然后返回一个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());
}
传入一个迭代器,返回一个ArrayList
public static ArrayList newArrayList(Iterator extends E> elements) {
ArrayList list = newArrayList();
//根据Iterators中的addAll方法将迭代器中的源码装入list集合中
Iterators.addAll(list, elements);
return list;
}
传入想要的list长度,返回一个与传入值等长的ArrayList
//直接返回一个新的ArrayList,并且长度为传入的长度
public static ArrayList newArrayListWithCapacity(int initialArraySize) {
CollectPreconditions.checkNonnegative(initialArraySize, "initialArraySize");
return new ArrayList(initialArraySize);
}
传入一个想要的list长度,返回一个程序调优后的长度的ArrayList
public static ArrayList newArrayListWithExpectedSize(int estimatedSize) {
return new ArrayList(computeArrayListCapacity(estimatedSize));//返回一个长度调优后的ArrayList
}
不传入参数,直接返回一个LinkedList
public static LinkedList newLinkedList() {
return new LinkedList();//直接返回一个LinkedList
}
传入一个容器,返回一个LinkedList
public static LinkedList newLinkedList(Iterable extends E> elements) {
LinkedList list = newLinkedList();
//将传入的容器,使用Iterables的addAll方法进行的数据转移
Iterables.addAll(list, elements);
return list;
}
不传入参数,直接返回一个新的CopyOnWriteArrayList
public static CopyOnWriteArrayList newCopyOnWriteArrayList() {
return new CopyOnWriteArrayList();//直接返回一个新的CopyOnWriteArrayList
}
传入一个容器,返回一个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);
}
使用案例:
String leader = "leader";
String[] members = {"member1", "member2", "member3"};
List group = Lists.asList(leader, members);
System.out.println(group);
这样做的一个好处是可以提高代码的可读性,因为它明确地区分了 "leader" 和 "members",而不是将它们混在一起。而且,如果 "members" 是动态确定的(例如,它们来自另一个方法或计算结果),那么这个 asList
方法将比手动创建 List
并添加元素更为方便。
注意:asList返回的是视图,也就是说,原容器的变更会影响这些方法返回的容器内容
根据参数生成一个多一个参数的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];
}
}
根据参数生成一个多两个个参数的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];
}
}
}
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 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进行分类处理
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();
}
}
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方法进行处理的逆序
private Maps() {
}
私有的构造方法,可以看到这是一个真正的功能函数,下面对其函数进行分析
功能 | 方法 |
---|---|
创建EnumMap | 1、EnumMap 2、EnumMap |
返回不可变EnumMap | ImmutableMap |
创建HashMap | 1、HashMap 2、HashMap 3、HashMap |
创建LinkedHashMap | 1、LinkedHashMap 2、LinkedHashMap |
创建ConcurrentMap | ConcurrentMap |
创建TreeMap | 1、TreeMap 2、TreeMap 3、TreeMap |
创建IdentityHashMap | IdentityHashMap |
获取两个Map中不同元素的值 | 1、MapDifference 2、MapDifference 3、SortedMapDifference |
根据函数和set,构造Map | 1、Map 2、SortedMap 3、NavigableMap |
根据函数和迭代器,构造不可变的Map | 1、ImmutableMap 2、ImmutableMap 3、ImmutableMap 4、ImmutableMap |
从配置文件中读取数据,创建不可变的Map | ImmutableMap |
返回Entry或Entry集合 | 1、Entry 2、Set 3、Entry |
返回特殊的BiMap类 | 1、BiMap 2、BiMap |
根据Map和函数对Map进行转型 | 1、Map 2、SortedMap 3、NavigableMap 4、Map 5、SortedMap 6、NavigableMap |
使用函数进行过滤Map,然后返回同类型的Map | 分为4种过滤 一、针对Key进行过滤 1.Map 2.SortedMap 3.NavigableMap 4.BiMap 二、针对Value进行过滤 1.Map 2.SortedMap 3.NavigableMap 4.BiMap 三、针对Entry进行过滤 1.Map 2.SortedMap 3.SortedMap 4.NavigableMap 5.BiMap 四、为含有过滤规则的Map进行过滤 1.Map 2.SortedMap 3.NavigableMap 4.BiMap |
传入一个Class变量,返回一个EnumMap
public static , V> EnumMap newEnumMap(Class type) {
return new EnumMap((Class)Preconditions.checkNotNull(type));
}
传入一个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);
}
}
传入一个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
public static HashMap newHashMap() {
return new HashMap();
}
返回一个有初始长度的HashMap
public static HashMap newHashMapWithExpectedSize(int expectedSize) {
return new HashMap(capacity(expectedSize));
}
//根据传入的长度,返回一个实际可用expectedSize的HashMap,capacity方法就是计算实际长度的一个方法
static int capacity(int expectedSize) {
if(expectedSize
这里为什么是 0.75这个系数呢?
传入一个Map型变量,返回一个HashMap
public static HashMap newHashMap(Map extends K, ? extends V> map) {
return new HashMap(map);//这个步骤就由HashMap的putMapEntries方法进行操作了
}
直接返回一个新的LinkedHashMap
public static LinkedHashMap newLinkedHashMap() {
return new LinkedHashMap();
}
传入一个Map变量,返回一个LinkedHashMap
public static LinkedHashMap newLinkedHashMap(Map extends K, ? extends V> map) {
return new LinkedHashMap(map);//这个步骤就由LinkedHashMap的putMapEntries方法进行操作了。
}
直接返回一个新的ConcurrentMap
public static ConcurrentMap newConcurrentMap() {
return new ConcurrentHashMap();
}
直接返回一个新的TreeMap
public static TreeMap newTreeMap() {
return new TreeMap();
}
传入一个Map变量,返回一个TreeMap,并将Map的值赋值给TreeMap
public static TreeMap newTreeMap(SortedMap map) {
return new TreeMap(map);
}
传入一个比较接口,返回一个根据传入的比较规则形成的TreeMap
public static TreeMap newTreeMap(@Nullable Comparator comparator) {
return new TreeMap(comparator);
}
直接返回一个identityHashMap
public static IdentityHashMap newIdentityHashMap() {
return new IdentityHashMap();
}
IdentityHashMap与HashMap不同之处在于可以存入相同类的相同值,实际上他在put里的添加操作是不是使用equals而是用的==进行判断的
在说明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个变量
传入两个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;
}
}
传入两个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);
}
}
}
传入一个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
和一个Function
结合起来,创建一个视图(view),这个视图在每次查询时通过应用函数来动态生成键值对。
AsMapView
创建的是一个视图,而不是一个独立的新集合。这意味着原始集合(Set
)的任何修改都会反映在AsMapView
中,反之亦然。这种行为类似于如何通过Collections.unmodifiableList()
方法得到的不可修改的视图,但AsMapView
是可修改的,其修改会影响到原始的集合。AsMapView
在实际调用其get()
方法之前不会计算键对应的值。这意味着如果你有一个非常昂贵的转换逻辑,它只有在实际需要该值时才会执行,这有助于提高效率。AsMapView
使用了提供的Set
和Function
来实现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
方法介绍:
传入一个set和一个规则,返回一个Map
public static Map asMap(Set set, Function super K, V> function) {
return new AsMapView(set, function);
}
传入一个SortedSet和一个规则,返回一个SortMap
public static SortedMap asMap(SortedSet set, Function super K, V> function) {
return new SortedAsMapView(set, function);
}
传入一个NavigableSet和一个规则,返回一个NavigableMap
public static NavigableMap asMap(NavigableSet set, Function super K, V> function) {
return new Maps.NavigableAsMapView(set, function);
}
此类方法传入的是一个容器的迭代器和一个规则,然后返回一个不可变的Map容器
传入一个key值容器和一个规则,直接交给重载函数去处理,返回一个不可变的Map容器
public static ImmutableMap toMap(Iterable keys, Function super K, V> valueFunction) {
return toMap((Iterator)keys.iterator(), valueFunction);
}
传入一个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);
}
根据value值容器和一个规则,直接交给重载函数去处理,返回一个不可变的Map容器
public static ImmutableMap uniqueIndex(Iterable values, Function super V, K> keyFunction) {
return uniqueIndex((Iterator)values.iterator(), keyFunction);
}
传入一个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获取的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();
}
传入一个key和一个value,返回一个不可变的Entry
public static Entry immutableEntry(@Nullable K key, @Nullable V value) {
return new ImmutableEntry(key, value);
}
Guava 提供了 BiMap 支持支持双向的映射关系,关于BiMap详情可以看后文
传入一个BiMap返回一个线程安全的BiMap
public static BiMap synchronizedBiMap(BiMap bimap) {
return Synchronized.biMap(bimap, (Object)null);
}
传入一个BiMap返回一个unmodifiableBiMap
public static BiMap unmodifiableBiMap(BiMap extends K, ? extends V> bimap) {
return new Maps.UnmodifiableBiMap(bimap, (BiMap)null);
}
此类方法使用使用到了函数式编程,将一个Map的value作为新的Map的key,根据函数的规则计算出新的Map的Value,而这个转换只有在查看的时候才会做计算,而真正存储的是传入的map
传入一个Map和一个规则,返回一个有规则计算出来的Map
public static Map transformValues(Map fromMap, Function super V1, V2> function) {
return transformEntries((Map)fromMap, asEntryTransformer(function));
}
传入一个SortedMap和一个规则,返回一个由规则计算出来的新的Map
public static SortedMap transformValues(SortedMap fromMap, Function super V1, V2> function) {
return transformEntries((SortedMap)fromMap, asEntryTransformer(function));
}
传入一个NavigableMap和一个规则,返回一个由规则计算出来的NavigableMap
public static NavigableMap transformValues(NavigableMap fromMap, Function super V1, V2> function) {
return transformEntries((NavigableMap)fromMap, asEntryTransformer(function));
}
传入一个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));
}
传入一个NavigableMap和一个Maps规定的规则格式,根据规则返回一个新的NavigableMap
public static NavigableMap transformEntries(NavigableMap fromMap, Maps.EntryTransformer super K, ? super V1, V2> transformer) {
return new Maps.TransformedEntriesNavigableMap(fromMap, transformer);
}
这里我们主要针对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);
}
}
传入一个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));
}
传入一个SortedMap,然后交给filterEntries方法进行处理
public static SortedMap filterKeys(SortedMap unfiltered, Predicate super K> keyPredicate) {
return filterEntries(unfiltered, keyPredicateOnEntries(keyPredicate));
}
传入一个NavigableMap,然后交给filterEntries方法进行处理
public static NavigableMap filterKeys(NavigableMap unfiltered, Predicate super K> keyPredicate) {
return filterEntries((NavigableMap)unfiltered, keyPredicateOnEntries(keyPredicate));
}
传入一个BiMap,然后交给filterEntries方法进行处理
public static BiMap filterKeys(BiMap unfiltered, Predicate super K> keyPredicate) {
Preconditions.checkNotNull(keyPredicate);
return filterEntries((BiMap)unfiltered, keyPredicateOnEntries(keyPredicate));
}
功能 | 方法 |
---|---|
创建不可变的set | 1、ImmutableSet 2、ImmutableSet |
创建HashSet | 1、HashSet 2、HashSet 3、HashSet 4、HashSet 5、HashSet |
创建线程安全的Set | 1、Set 2、Set |
创建LinkedHashMap | 1、LinkedHashSet 2、LinkedHashSet 3、LinkedHashSet |
创建TreeSet | 1、TreeSet 2、TreeSet 3、TreeSet |
创建IdentityHashSet | Set |
创建CopyOnWriteArraySet | 1、CopyOnWriteArraySet 2、CopyOnWriteArraySet |
创建EnumSet | 1、EnumSet 2、EnumSet 3、EnumSet 4、EnumSet |
根据Map创建一个Set | Set |
以两个Set的并集作为视图 | Sets.SetView |
以两个Set的交集作为视图 | Sets.SetView |
以两个Set的互不重叠的部分作为视图 | Sets.SetView |
以两个Set的对称部分作为视图 | Sets.SetView |
过滤Set | 1、filter(Set 2、SortedSet 3、SortedSet 4、NavigableSet |
获取两个Set集合的笛卡尔积 | 1、Set
2、Set
|
根据传入的参数,创建一个不可变的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;
}
根据一个集合创建一个不可变的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();
}
}
}
直接new一个HashSet
public static HashSet newHashSet() {
return new HashSet();
}
传入一个数组,返回一个HashSet
public static HashSet newHashSet(E... elements) {
//创建一个期望大小为elements.length的HashSet
HashSet set = newHashSetWithExpectedSize(elements.length);
//将数组中的元素,全部赋值给新的HashSet
Collections.addAll(set, elements);
return set;
}
创建一个期望大小的HashSet
public static HashSet newHashSetWithExpectedSize(int expectedSize) {
//创建一个HashSet,大小为Maps.capacity方法计算后的值,这个方法最终返回原值的4/3
return new HashSet(Maps.capacity(expectedSize));
}
根据传入的集合创建一个HashSet
public static HashSet newHashSet(Iterable extends E> elements) {
return elements instanceof Collection?new HashSet(Collections2.cast(elements)):newHashSet((Iterator)elements.iterator());
}
根据传入的迭代器创建一个HashSet
public static HashSet newHashSet(Iterator extends E> elements) {
//创建一个HashSet
HashSet set = newHashSet();
//使用Guava中的Iterators.addAll方法将迭代器中的元素添加到set中
Iterators.addAll(set, elements);
return set;
}
使用ConcurrentHashMap创建一个Set
public static Set newConcurrentHashSet() {
//创建一个ConcurrentHashMap,使用newSetFromMap方法将ConcurrentHashMap的值转为Set
return newSetFromMap(new ConcurrentHashMap());
}
使用传入的集合创建一个线程安全的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
public static LinkedHashSet newLinkedHashSet() {
return new LinkedHashSet();
}
创建一个期望大小的LinkedHashSet
public static LinkedHashSet newLinkedHashSetWithExpectedSize(int expectedSize) {
//返回一个LinkedHashSet,大小为expectedSize的4/3
return new LinkedHashSet(Maps.capacity(expectedSize));
}
根据传入的集合,返回一个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
public static TreeSet newTreeSet() {
return new TreeSet();
}
传入一个集合,返回一个TreeSet,并将集合中的元素赋值给TreeSet
public static TreeSet newTreeSet(Iterable extends E> elements) {
//创建一个TreeSet
TreeSet set = newTreeSet();
//将集合中的元素赋值给TreeSet
Iterables.addAll(set, elements);
return set;
}
传入一个Comparator,根据Comparator的规则创建一个TreeSet
public static TreeSet newTreeSet(Comparator super E> comparator) {
return new TreeSet((Comparator)Preconditions.checkNotNull(comparator));
}
根据Maps.newIdentityHashMap()和Sets.newSetFromMap两个方法创建一个IdentityHashSet
public static Set newIdentityHashSet() {
//使用Maps.newIdentityHashMap()方法创建一个IdentityHashMap,然后使用newSetFromMap方法将Map转为Set
return newSetFromMap(Maps.newIdentityHashMap());
}
直接创建一个CopyOnWriteArraySet
public static CopyOnWriteArraySet newCopyOnWriteArraySet() {
return new CopyOnWriteArraySet();
}
根据传入的集合创建一个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
public static > EnumSet newEnumSet(Iterable iterable, Class elementType) {
//根据传入的类型,创建一个set
EnumSet set = EnumSet.noneOf(elementType);
//将集合中的元素添加到set中
Iterables.addAll(set, iterable);
return set;
}
传入一个集合,返回一个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
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,返回一个两个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);
}
};
}
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();
}
};
}
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);
}
};
}
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的过滤和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
参与评论
手机查看
返回顶部