(1)构造不可变集合
不可变集合的优点:
1. 避免别人调用时更改集合内容
2. 线程安全:因为是只读的,所以多线程条件下是安全的
3. 不必考虑集合变化,所以会比可变的集合更加的有效率
4. 可以作为常量使用
JDK里面Collections.unmodifiableXXX也可以得到不可变的集合,但是是有缺陷的:
1. api不友好,用起来麻烦
2. 不安全的,unmodifiableXXX返回的集合确实不可以直接修改,但是可以通过修改原集合元素来改变返回的集合。
3. 低效的:数据结构依然含有可变集合的特性,如并发修改检查,hashtable中的额外空间等。
所以:当你期望一个集合不要被更改,或者想把一个集合当常量使用,那就把它变成immutable吧。
需要注意的是:guava的immutable集合不允许包含null值,他们对google内部代码做了研究,认为95%的情况,不允许包含null值会更方便。
如果你实在希望immutable集合允许包含null值,那就只有用jdk的Collections.unmodifiableXXX了。
在guava中,ImmutableXXX有三种方法可以得到:
1. 使用copyOf方法,如:ImmutableSet.copyOf(set)
2. 使用of方法,如:ImmutableSet.of("a", "b", "c") or ImmutableMap.of("a", 1, "b", 2)
3. 使用Builder,如:
public static final ImmutableSet<Color> GOOGLE_COLORS =
ImmutableSet.<Color>builder()
.addAll(WEBSAFE_COLORS)
.add(new Color(0, 191, 255))
.build();
智能的copyOf:
copyOf方法会根据实际情况,决定是否通过全量copy的方式生成不可变集合。
可以直接来看ImmutableList的copyOf方法:
public static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) {
if (elements instanceof ImmutableCollection) {
@SuppressWarnings("unchecked") // all supported methods are covariant
ImmutableList<E> list = ((ImmutableCollection<E>) elements).asList();
return list.isPartialView() ? copyFromCollection(list) : list;
}
return copyFromCollection(elements);
}
1. 如果集合本身就是不可变的,就会考虑直接返回集合的asList(),否则就做全量copy。
2. 如果copyOf集合的部分元素,还是需要做copy的
3. copyOf的其他重构方法可以看到:如果原集合和不可变集合类型不同,就需要做全量copy。
Interface |
JDK or Guava? |
Immutable Version |
Collection |
JDK |
|
List |
JDK |
|
Set |
JDK |
|
JDK |
||
Map |
JDK |
|
SortedMap |
JDK |
|
Multiset(可放重复元素的set,有方法返回元素出现的次数) |
Guava |
|
SortedMultiset(有序的multiset) |
Guava |
|
Multimap(key可重复的map,有方法返回指定key的所有value) |
Guava |
|
ListMultimap(value采用list存储的Multimap,实现类很多:如LinkedListMultimap,ArrayListMultimap等等) |
Guava |
|
SetMultimap(value采用set存储的Multimap,同样,实现类很多:如MapMultimap,LinkedHashMultimap等等) |
Guava |
|
Guava |
||
ClassToInstanceMap(key是class的map) |
Guava |
|
Table(x,y,value)的格式存储数据,可以通过坐标(x,y)查找元素 |
Guava |
|
RangeSet 元素是Range的set,Range表示一个区域,类似 (2,4) [2,4]等。有方法可以判定区域的包含关系,或者将多个区域并为一个。 |
ImmutableRangeSet |
|
RangeMap 元素是Range的map |
Guava |
ImmutableRangeMap |
(2)集合帮助类:
就像JDK里面Collections提供了很多实用方法一样,guava也针对不同的集合类提供了帮助类。
Interface |
JDK or Guava? |
Corresponding Guava utility class |
Collection |
JDK |
Collections2 (avoiding conflict with java.util.Collections) |
List |
JDK |
|
Set |
JDK |
|
SortedSet |
JDK |
|
Map |
JDK |
|
SortedMap |
JDK |
|
Queue |
JDK |
|
Guava |
||
Guava |
||
Guava |
||
Guava |
还有个比较特殊的帮助类:Iterables
Google推荐处理集合类的api最好针对Iterable,而不是Collection。
我们知道Collection实现了Iterable,Iterable其实只有一个方法iterator(),实现该方法的对象就可以使用foreach来遍历该集合。
很多时候,我们无法一次性得到集合的所有元素(比如数据来自db或者另一个数据中心),所以size()方法是无法实现的,这时候,如果我们实现Iterable的话,就只需要实现iterator()方法。
Iterables是针对Iterable的帮助类,Guava12以后,又增加了一个FluentIterable类来处理Iterable。基本上Iterables的方法在FluentIterable中都有对应的实现。
Iterables的方法都是static的;FluentIterable实现了Iterable接口,方法都是非static的
FluentIterable.from(Iterable iterable)可以把iterable封装为FluentIterable对象,然后就可以使用那些非static的方法了。
集合帮助类一般包含3种api:
(1) 静态工厂方法:构造集合的方法,上面的表格基本说明了构造各种集合该用哪种帮助类。一般是XxxS.newXX()或者Xxxs.create()方法来构造集合。
(2) 包装方法:包装成Unmodifiable,Synchronized
(3) 特色方法:如lists可以对集合的元素分组,sets可以对集合执行并交差操作。
下面重点介绍下特色方法:
1. Iterables & FluentIterable
Iterable中的方法:
(1) concat(Iterable<Iterable>) 合并多个Iterable集合为一个
(2) frequency(Iterable, Object) 统计对象出现次数
(3) partition(Iterable, int) 按一定尺寸进行分段 paddedPartition会用null填充少的元素
(4) getFirst(Iterable, T default) 得到第一个对象
(5) getLast(Iterable) 得到最后一个对象
(6) elementsEqual(Iterable, Iterable) 比较Iterable的所有元素是否顺序相同且相等
(7) unmodifiableIterable(Iterable) 得到不可变的集合视图
(8) limit(Iterable, int) 取前n个元素构成集合
(9) getOnlyElement(Iterable) 返回Iterable中的唯一元素,必须保证Iterable只有1个元素
FluentIterable中还有如下的方法:
ImmutableList toImmutableList() 使用Iterable构造不可变的List
ImmutableSet toImmutableSet() 使用Iterable构造不可变的Set
ImmutableSortedSet toImmutableSortedSet(Comparator) 使用Iterable,采用Comparator指定的排序方式构造有序的Set
此外,Iterables & FluentIterable还有类似Collections对Collection对象操作的方法,可以对Iterable进行集合相关的操作
2. Lists
partition(List, int) 按照指定size对list进行分组
reverse(List)倒序,注意:如果list是Immutable的,考虑使用ImmutableList.reverse() 代替
3. Sets
union(Set, Set) 并集
intersection(Set, Set) 交集
difference(Set, Set) 差集 set1中存在,set2中不存在
symmetricDifference(Set, Set) 对称差集 (set1和set2中出现,但不同时出现)
cartesianProduct(List<Set>) 笛卡尔积
powerSet(Set) 所有可能的子集合
4. Maps
uniqueIndex(Iterable, Function) 这个很有用,希望构造另一个Map,key是Function转换后的对象,value就是Iterable的元素。用于实现key查找value,key通过Function来构造。
difference(Map, Map) 比较2个map的差异,返回的MapDifference
对象可以比较包括key和value的差异
synchronizedBiMap(BiMap) 构造线程安全的biMap
unmodifiableBiMap(BiMap) 构造Immutable的biMap
5. Multisets
containsOccurrences(Multiset sup, Multiset sub) 判断所有元素在sup中出现的次数是否都大于等于sub中出现的次数
removeOccurrences(Multiset removeFrom, Multiset toRemove) 从removeFrom中移除对象在toRemove中出现的次数
retainOccurrences(Multiset removeFrom, Multiset toRetain) 从removeForm中保留toRetain中出现的次数
intersection(Multiset, Multiset) 返回2个Multiset的交集,2个集合中都包含,保留出现次数少的次数
copyHighestCountFirst(Multiset) 得到immutable的Multiset,按出现次数排序
unmodifiableMultiset(Multiset) 返回immutable的Multiset
unmodifiableSortedMultiset(SortedMultiset) 返回immutable的SortedMultiset
6. Multimaps
index(Iterable, Function) 跟Mpas. uniqueIndex类似,但是同一个key可以包含多个value
invertFrom(Multimap toInvert, Multimap dest) 倒序,注意:如果toInvert是immutable的,考虑使用 ImmutableMultimap.inverse()代替
forMap(Map) 使用Map构造Multimaps,结合invertFrom可以轻松实现map中通过value找key。
7. Tables
newCustomTable(Map, Supplier<Map>) 使用指定的值来构造Table对象,Map是(x,y),Supplier<Map>是value。
transpose(Table<R, C, V>) (x,y)换成(y,x)
(3)实现自己的集合类
1. Forwarding Decorators
有时候,我们自己实现的集合,有些特殊的需求,比如元素加入或删除时记日志,发消息;再比如元素的加入删除读取,其实是对db或者文件的操作。这时候我们可以直接继承guava提供的抽象父类。
例如,下面是自己实现的list,在加入元素时打下日志。
class AddLoggingList<E> extends ForwardingList<E> {
final List<E> delegate; // backing list
@Override protected List<E> delegate() {
return delegate;
}
@Override public void add(int index, E elem) {
log(index, elem);
super.add(index, elem);
}
@Override public boolean add(E elem) {
return standardAdd(elem); // implements in terms of add(int, E)
}
@Override public boolean addAll(Collection<? extends E> c) {
return standardAddAll(c); // implements in terms of add
}
}
类似List,其他的集合类都有对应的抽象父类
Interface |
Forwarding Decorator |
Collection |
|
List |
|
Set |
|
SortedSet |
|
Map |
|
SortedMap |
|
ConcurrentMap |
|
Map.Entry |
|
Queue |
|
Iterator |
|
ListIterator |
|
Multiset |
|
Multimap |
|
ListMultimap |
|
SetMultimap |
2. PeekingIterator
iter.next() 会返回集合当前遍历到的元素,有时候我们需要比较当前元素和下一个元素,根据比较结果来决定当前元素的取舍。如果自己实现,可能需要使用额外的变量保存当前值。
PeekingIterator实现了Iterator,但是他不仅有next()方法,还有个peek()方法,返回再下一个元素,但是遍历指针不会向前移动。这样就可以方便把当前元素跟下一个元素对比,来决定当前元素做些神马操作(next?remove?)
下面示例代码可以去重连续重复的元素。Iterators.peekingIterator(Iterator)可以将普通Iterable封装为PeekingIterator
List<E> result = Lists.newArrayList();
PeekingIterator<E> iter = Iterators.peekingIterator(source.iterator());
while (iter.hasNext()) {
E current = iter.next();
while (iter.hasNext() && iter.peek().equals(current)) {
// skip this duplicate element
iter.next();
}
result.add(current);
}
3.AbstractIterator
假如我们自己实现Iterator,考虑的重点应该是如何获取下一个元素,以及是否还有下一个元素。
继承AbstractIterator,我们可以通过实现computeNext()方法来完成这一点,其他的我们就不用操心了。当然,如果没有下一个元素了,我们可以调用endOfData方法
例如,下面的代码返回的自定义Iterator可以跳过null值。
public static Iterator<String> skipNulls(final Iterator<String> in) {
return new AbstractIterator<String>() {
protected String computeNext() {
while (in.hasNext()) {
String s = in.next();
if (s != null) {
return s;
}
}
return endOfData();
}
};
}
4.AbstractSequentialIterator
如果,我们计算下一个元素需要前一个参数作为依据,可以考虑实现AbstractSequentialIterator。
它的computeNext方法会传一个参数,代表集合前一个值。与AbstractIterator
不同,如果想让集合马上结束,返回null即可。此外,AbstractSequentialIterator的构造方法必须指定集合的第一个值是多少,如果是null,则是个空iterator。
下面的例子构造了一个Iterator,返回2的n次方
Iterator<Integer> powersOfTwo = new AbstractSequentialIterator<Integer>(1) { // note the initial value!
protected Integer computeNext(Integer previous) {
return (previous == 1 << 30) ? null : previous * 2;
}
};
相关推荐
本学习笔记将重点介绍Guava中的几个核心工具类:Joiner、Splitter、Preconditions。 1. Joiner类与Splitter类 Joiner类的主要功能是将集合中的元素拼接成一个字符串。通过指定分隔符,可以灵活地将集合或Map中的...
Guava学习笔记笔记的大部分中文翻译内容来源于以下译者: 沉义扬,罗立树,何一昕,武祖校对:方腾飞感谢给我们带来的这一系列好文章。引言Guava工程包含了若干被Google的Java项目广泛依赖的核心库,例如:集合...
2. **缓存**:Guava提供了本地缓存机制,可以帮助开发者创建高效的应用,通过自动管理缓存项的过期和清除,减少不必要的计算或远程调用。 3. **函数式编程**:Guava引入了函数接口,如Function、Predicate等,这些...
Guava是Google提供的一个强大的Java库,提供了许多实用功能,例如集合框架的扩展、缓存、并发工具等。在处理空集合时,Guava提供了更安全的API。比如,Guava的`Optional<T>`类可以用来表示一个值可能存在也可能不...
2. "AnOverviewofGuavaDevoxxFRApril2012.pdf" 另一份文档可能是同年4月在Devoxx France会议上对Guava的介绍,内容可能与前一份相似,但可能更侧重于法国开发者关心的议题或使用场景。 3. "JavaCachingwithGuava....
4. **集合框架**:List(如ArrayList和LinkedList)、Set(如HashSet和TreeSet)和Map(如HashMap和TreeMap)接口及其实现类的使用。 5. **IO流**:输入/输出流的理解,包括字节流和字符流,以及缓冲流、对象流和...
Guava是Google提供的开源Java库,它包含了大量有用和高效的工具类,例如用于集合操作的工具类,它简化了常见的集合操作,提高了代码的可读性和可维护性。Apache Commons也是一个流行的开源Java库,它提供了很多实用...
最后,笔记可能涵盖了其他工具类和框架的使用,例如Spring框架用于依赖注入和AOP(面向切面编程),MyBatis简化SQL操作,还有可能涉及Apache Commons或Google Guava等实用工具库,它们提供了许多方便的函数和数据...
例如,“对手分布函数库”可能指的是在Java中使用不同的库(如Apache Commons或Guava)来处理数据分布或算法;“空间不能快速的纪念版”可能是指内存管理或性能优化问题;“上课了半年”暗示了作者正在进行长期的...
同时,后端与前端的交互过程中,JWT用于身份验证,Guava提供了额外的工具类和集合类,JMeter5.X用于性能测试,确保系统的稳定性和性能。 在部署环节,文档提到了使用CentOS7作为服务器操作系统,Nginx作为反向代理...
笔记 Java 语言相关的API,第三方库和计算机基础理论等知识的学习和整理 更多 : | | 目录 资源 详细目录 Java语言和JDK源码 Java语言的基础理论知识 并发编程 Java并发编程相关的内容,并发包源码分析等 集合框架 ...
此外,Guava库提供了更丰富的工具类,如Preconditions、Lists、Maps等,提高了开发效率。 以上五个部分构成了Java编程的基础,掌握这些知识点能够帮助开发者构建高效、稳定的系统。在实际工作中,结合具体需求,...
heavyz的Tomcat学习笔记(包括启动流程分析、启动脚本分析) ] () [ java8 新特性讲解系列文章 ] () [ Java 从Jar文件中动态加载类 ] () [ Java并发源码分析 - ThreadPoolExecutor ] () [ java ClassLoader 基本原理 ]...
2. **类与对象**:这是面向对象编程的基础,包括类的定义、对象的创建、封装、继承、多态等概念。 3. **异常处理**:Java的异常处理机制是通过try-catch-finally语句块来实现的,了解如何正确捕获和处理异常对于...
集合 ConcurrentMap原理: 并发 java并发编程--Executor框架(一) 怎么理解Condition JAVA细粒度锁实现的几种方式: NIO,IO 注解 [笔记] dagger2: Retrofit和ButterKnife的注解怎么实现 反射 JOOR [ClassLoader==>...
这个压缩包中可能包含了大量的教程、示例代码、笔记文档和其他相关材料,为初学者和经验丰富的开发者提供了丰富的学习资源。 1. **基础语法**:Java的基础语法是学习的起点,包括数据类型(如基本类型和引用类型)...
最后,压缩包可能还包括一些文档、教程或者笔记,这些资料可能涵盖了Java的基础知识,如语法、垃圾回收机制,以及更高级的主题,如反射、动态代理和Java集合框架等。通过阅读这些文档,开发者能够系统地学习Java,...
它旨在帮助开发者通过Markdown格式整理和分享他们的学习笔记,同时也涵盖了其他技术领域如Vue.js、Node.js、Android学习以及Guava库的常用解析。 【描述】该项目可能是正在进行中的工作,因为提到了"可能未完结",...
【标题】"PubLearnNotes" 是一个公开的学习笔记集合,主要涵盖了作者在IT领域的学习历程,尤其是关于Java编程语言的知识点。这个资源可能是作者为了方便自己随时查阅和更新而创建的,同时也分享给了对相关技术感兴趣...
Java语言的特点包括跨平台性(得益于"一次编写,到处运行"的JVM)、强大的库支持(如Apache Commons、Google Guava等)、以及丰富的生态系统(如Maven Central仓库)。在实际开发中,Java被广泛应用于Web应用、大...