场景
Java核心工具库Guava介绍以及Optional和Preconditions使用进行非空和数据校验:
Java核心工具库Guava介绍以及Optional和Preconditions使用进行非空和数据校验_霸道流氓气质的博客-CSDN博客_guava 校验
在上面引入Guava的基础上。学习其不可变集合和新集合类型的使用
不可变集合
1、当对象被不可信的库调用时,不可变形式是安全的。
2、不可变对象被多个线程调用时,不存在竞态条件问题。
3、不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比他们的可变形式有更好的内存利用率。
4、不可变对象因为固定不变,可以作为常量来安全使用。
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。
不可变集合的创建
1、copyOf方法
//创建不可变集合的方式
List<String> list = new ArrayList<String>(){{
this.add("badao");
this.add("de");
this.add("chengxvyuan");
}};
//1、copyOf方法
ImmutableList<String> strings = ImmutableList.copyOf(list);
System.out.println(strings);//[badao, de, chengxvyuan]
list.add("add");
System.out.println(strings);//[badao, de, chengxvyuan]
并且当原集合改变时,copy的不会改变
2、of方法
ImmutableList<String> of = ImmutableList.of("a", "b", "d", "c");
System.out.println(of);//[a, b, d, c]
3、Builder工具
ImmutableSet<Object> add = ImmutableSet.builder()
.addAll(list)
.add("add")
.build();
System.out.println(add);//[badao, de, chengxvyuan, add]
ImmutableSortedSet有序不可变集合
对于有序不可变集合,排序在构造集合时就完成
ImmutableSortedSet<String> of2 = ImmutableSortedSet.of("a", "d", "a", "c", "b", "a");
System.out.println(of2);//[a, b, c, d]
asList视图
所有不可变集合都有一个asList()方法提供ImmutableList视图
System.out.println(ImmutableSet.of("a","a","b","c").asList());//[a, b, c]
System.out.println(ImmutableSet.of("a","a","b","c").asList().get(0));//a
新集合类型
Multiset
Multiset,可以多次添加相等的元素,Multiset元素顺序是无关的,Multiset{a,a,b} 与{a,b,a}是相等的
可以将其看做是没有元素顺序限制的ArrayList
1、添加单个给定元素
Multiset<String> multiSet = HashMultiset.create();
multiSet.add("badao");
multiSet.add("badao");
multiSet.add("de");
multiSet.add("de");
2、获取元素个数
System.out.println(multiSet.size());//4
3、添加多个给定元素
List<String> list = new ArrayList<String>(){{
this.add("badao");
this.add("de");
this.add("chengxvyuan");
}};
//size获取元素个数
System.out.println(multiSet.size());//4
//添加多个给定元素
multiSet.addAll(list);
System.out.println(multiSet.size());//7
4、iterator()返回一个迭代器,包含Multiset的所有元素(包括重复元素)
Iterator<String> it = multiSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
也可以将其看做是Map<E,Interger> 键为元素,值为计数
1、count(Object)返回给定元素的计数
System.out.println("badao元素的计数为:"+multiSet.count("badao"));//badao元素的计数为:3
2、elementSet() Multiset不重复元素的集合,类型为Set<E>
System.out.println(multiSet.elementSet());//[badao, de, chengxvyuan]
3、entrySet()和Map的entrySet类似,返回Set<Multiset.Entry<E>> 其中包含的Entry支持getElement()和getCount()方法
multiSet.entrySet().forEach(stringEntry -> {
System.out.println(stringEntry.getElement()+stringEntry.getCount());
});
4、add(E,int) 增加给定元素在Multiset中的计数
System.out.println( multiSet.count("badao"));//3
multiSet.add("badao",3);
System.out.println(multiSet.count("badao"));//6
5、设置给定元素在Multiset中的计数
multiSet.setCount("badao",1);
System.out.println(multiSet.count("badao"));//1
SortedMultiset
SortedMultiset是Multiset接口的变种,它支持高效地获取指定范围的子集
SortedMultiset sortedMultiset = TreeMultiset.create();
sortedMultiset.add(0);
sortedMultiset.add(1);
sortedMultiset.add(2);
sortedMultiset.add(2);
sortedMultiset.add(3);
sortedMultiset.add(5);
sortedMultiset.add(6);
sortedMultiset.add(8);
sortedMultiset.add(9);
//统计在0到5以内的数量,包含0,不包含5
int size = sortedMultiset.subMultiset(0, BoundType.CLOSED, 5, BoundType.OPEN).size();
int size1 = sortedMultiset.size();
// 创建一个数值格式化对象
NumberFormat numberFormat = NumberFormat.getInstance();
// 设置精确到小数点后2位
numberFormat.setMaximumFractionDigits(2);
String result = numberFormat.format((float)size/(float)size1);
System.out.println(result);//0.56
Multimap
Multimap 是把键映射到任意多个值的一般方式,不会有任何键映射到空集合:一个键要么至少到一个值,要么不存在Multimap中
1、Multimap的创建
Multimap multimap = HashMultimap.create();
2、添加键到单个值的映射
multimap.put("a",1);
multimap.put("a",2);
multimap.put("a",3);
multimap.put("b",3);
3、get(key)以集合形式返回键所对应的值视图,即使没有任何对应的值,也会返回空集合
Collection a = multimap.get("a");
System.out.println(a);//[1, 2, 3]
4、putAll(K,Iterable<V>) 依次添加键到多个值的映射
multimap.putAll("c",
new ArrayList(){
{
this.add(1);
this.add(2);
this.add(3);
this.add(4);
}
});
System.out.println(multimap.get("c"));//[1, 2, 3, 4]
5、remove(K,V)移除键到值的映射;如果有这样的键值并成功移除,返回true
multimap.remove("c",1);
System.out.println(multimap.get("c"));//[2, 3, 4]
6、removeAll(K) 清除键对应的所有值,返回的集合包含所有之前映射到K的值,但修改这个集合就不会影响到Multimap了
//multimap.removeAll("c");
System.out.println(multimap.get("c"));//[]
7、replaceValues(K,Iterable<K>)清除键对应的所有值,并重新把key关联到Iterable中的每个元素。
multimap.replaceValues("c",new ArrayList(){{
this.add(6);
this.add(7);
}});
System.out.println(multimap.get("c"));//[6, 7]
8、asMap为Multimap<K,V>提供Map<K,Collection>形式的视图。返回的Map支持remove操作,并且会
反映到底层的Multimap,但它不支持put或putAll操作。
Map map = multimap.asMap();
System.out.println(map);//{a=[1, 2, 3], b=[3], c=[6, 7]}
9、entries用Collection<Map.Entry<K,V>>返回Multimap中所有“键-单个值映射”,包括重复键
Collection entries = multimap.entries();
System.out.println(entries);//[a=1, a=2, a=3, b=3, c=6, c=7]
10、keySet用Set表示Multimap中所有不同的键
System.out.println(multimap.keySet());//[a, b, c]
11、keys用Multiset表示Multimap中的所有键,每个键重复出现的次数等于它映射的值的个数
可以从这个Multiset中移除元素,但不能做添加操作;移除操作会反映到底层的Multimap
System.out.println(multimap.keys());//[a x 3, b, c x 2]
12、values()用一个扁平的Collection包含Multimap中的所有值。
System.out.println(multimap.values());//[1, 2, 3, 3, 6, 7]
BiMap
BiMap<K,V>是特殊的Map: 可以用inverse()反转BiMap<K,V>的键值映射,保证值是唯一的,因此valus()返回Set而不是普通的Collection
1、在BiMap中,如果你想把键映射到已经存在的值,会抛出IllegalArgumentException
HashBiMap<String,Integer> biMap = HashBiMap.create();
biMap.put("a",1);
//biMap.put("b",1);//java.lang.IllegalArgumentException
2、如果对特定的值,想要强制替换它的键,使用forcePut
System.out.println(biMap.get("a"));//1
biMap.forcePut("b",1);
System.out.println(biMap.get("b"));//1
3、put和Inverse
HashBiMap<String,Integer> biMap2 = HashBiMap.create();
biMap2.put("a",1);
biMap2.put("a",2);
System.out.println(biMap2);//{a=2}
BiMap<Integer, String> inverse = biMap2.inverse();
System.out.println(inverse);//{2=a}
Table
Guava提供了Table,它有两个支持所有类型的键:“行“和”列“
1、put
HashBasedTable<Integer, Integer, String> table = HashBasedTable.create();
table.put(1,1,"java");
table.put(1,2,"c");
table.put(2,1,"c++");
table.put(2,2,"c#");
2、row(r)用Map<C,V>返回给定“行”的所有列,对这个map进行的写操作也将写入Table中
Map<Integer, String> row = table.row(1);
System.out.println(row);//{1=java, 2=c}
3、rowMap() 用Map<R,Map<C,V>> 表现Table<R,C,C>
Map<Integer, Map<Integer, String>> integerMapMap = table.rowMap();
System.out.println(integerMapMap);//{1={1=java, 2= c},2={1=c++, 2=c#}}
4、rowKeySet()返回行的集合set
Set<Integer> integers = table.rowKeySet();
System.out.println(integers);//[1, 2]
5、column 返回指定列
System.out.println(table.column(2));//{1=c, 2= c#}
6、columnMap 用Map<C,Map<R,V>> 表现Table<R,C,C>
System.out.println(table.columnMap());//{1={1=java, 2= c++},2={1=c, 2=c#}}
7、columnKeySet返回所有列的集合set
System.out.println(table.columnKeySet());//[1, 2]
8、cellSet()用元素类型为Table.Cell<R,C,V>的Set表现Table<R,C,V>
System.out.println(table.cellSet());//[(1,1)=java, (1,2)=c, (2,1)=c++, (2,2)=c#]
ClassToInstanceMap
ClassToInstanceMap是一种特殊的Map:它的键是类型,而值是符合键所指类型的对象。
ClassToInstabceMap额外声明了两个方法 T getInstance(Class) 和 T putInstance(Class,T),从而避免强制类型转换,同时保证了类型安全
ClassToInstanceMap<Number> instanceMap = MutableClassToInstanceMap.create();
instanceMap.putInstance(Integer.class,Integer.valueOf(0));
System.out.println(instanceMap.getInstance(Integer.class));//0
RangeSet
RangeSet描述了一组不相连的、非空的区间。当把一个区间添加到可变的RangeSet时,所有相连的区间会被合并,空区间会被忽略
1、创建和添加
RangeSet<Integer> rangeSet = TreeRangeSet.create();
rangeSet.add(Range.closed(1,10));
System.out.println(rangeSet);//[[1..10]]
rangeSet.add(Range.closedOpen(11,15));
System.out.println(rangeSet);//[[1..10], [11..15)]
rangeSet.add(Range.closedOpen(15,20));
System.out.println(rangeSet);//[[1..10], [11..20)]
rangeSet.add(Range.openClosed(0,0));
System.out.println(rangeSet);//[[1..10], [11..20)]
rangeSet.remove(Range.open(5,10));
System.out.println(rangeSet);//[[1..5], [10..10], [11..20)]
2、complement()返回RangeSet的补集视图
System.out.println(rangeSet.complement());//[(-∞..1), (5..10), (10..11), [20..+∞)]
3、subRangeSet(Range)返回RangeSet与Range的交集视图
System.out.println(rangeSet.subRangeSet(Range.closedOpen(15,30)));//[[15..20)]
4、asRanges()用Set<Range>表现RangeSet,这样可以遍历其中的Range
Set<Range<Integer>> ranges = rangeSet.asRanges();
System.out.println(ranges);//[[1..5], [10..10], [11..20)]
5、contains(C) 判断RangeSet中是否有任何区间包含给定元素
System.out.println(rangeSet.contains(6));//false
System.out.println(rangeSet.contains(11));//true
6、rangeContaining(C)返回包含给定元素的区间;若没有这样的区间,则返回null
System.out.println(rangeSet.rangeContaining(6));//null
System.out.println(rangeSet.rangeContaining(11));//[11..20)
7、encloses判断RangeSet中是否有任何区间包括给定区间
System.out.println(rangeSet.encloses(Range.closedOpen(11,15)));//true
System.out.println(rangeSet.encloses(Range.closedOpen(6,9)));//false
System.out.println(rangeSet.encloses(Range.closedOpen(15,25)));//false
8、span返回包含RangeSet中所有区间的最小区间
System.out.println(rangeSet.span());//[1..20)
RangeMap
RangeMap描述了“不想交的、非空的区间” 到特定值的映射,和RangeSet不同,RangeMap不会和并相邻的映射,即使相邻的区间映射到相同的值
1、创建和put
RangeMap<Integer,String> rangeMap = TreeRangeMap.create();
rangeMap.put(Range.closed(1,10),"badao");
System.out.println(rangeMap);//[[1..10]=badao]
rangeMap.put(Range.open(3,6),"de");
System.out.println(rangeMap);//[[1..3]=badao, (3..6)=de, [6..10]=badao]
rangeMap.put(Range.open(10,20),"chengxvyuan");
System.out.println(rangeMap);//[[1..3]=badao, (3..6)=de, [6..10]=badao, (10..20)=chengxvyuan]
rangeMap.remove(Range.closed(5,11));
System.out.println(rangeMap);//[[1..3]=badao, (3..5)=de, (11..20)=chengxvyuan]
2、asMapOfRanges() 用Map<Range,V>表现RangeMap,这可以用来遍历RangeMap
Map<Range<Integer>, String> rangeStringMap = rangeMap.asMapOfRanges();
System.out.println(rangeStringMap);//{[1..3]=badao, (3..5)=de, (11..20)=chengxvyuan}
3、subRangeMap(Range)用RangeMap类型返回RangeMap与给定Range的交集视图
System.out.println(rangeMap.subRangeMap(Range.closed(2,4)));//{[2..3]=badao, (3..4]=de}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135864.html