Guava 集合操作

不可变集合

不可变集合例子:

1
2
ImmutableSet<String> FRUITS = ImmutableSet.of("apple", "watermelon", "cherry", "mango");
FRUITS.remove("apple");

将抛出java.lang.UnsupportedOperationException异常: QQ截图20190422144849.png

创建不可变集合

of

1
2
ImmutableList<String> immutableList = ImmutableList.of("a", "b", "c");
ImmutableMap<Integer, String> immutableMap = ImmutableMap.of(1, "v1", 2, "v2", 3, "v3")

copyOf

1
2
Map<String, String> map = Maps.newHashMap();
ImmutableMap<String, String> immutableMap = ImmutableMap.copyOf(map);

builder

1
2
3
4
5
6
7
8
9
10
Map<String, String> map = Maps.newHashMap();
ImmutableMap<String, String> immutableMap = ImmutableMap.<String, String>builder()
.putAll(map)
.put("k1", "v1")
.build();

List<String> list = Lists.newArrayList();
ImmutableList<String> immutableList = ImmutableList.<String>builder()
.addAll(list)
.build();

除此之外,我们也可以从Java 8 Stream中创建不可变集合:

1
2
3
4
5
6
7
8
import static java.util.stream.Collectors.*;
...

List<String> list = Arrays.asList("a", "b", "c");
List<String> immutableList = list.stream()
.collect(collectingAndThen(toList(), ImmutableList::copyOf));

System.out.println(immutableList.getClass()); // class com.google.common.collect.RegularImmutableList

上面的例子我们也可以使用Guava提供的收集器:

1
2
3
4
5
List<String> list = Arrays.asList("a", "b", "c");
List<String> immutableList = list.stream()
.collect(ImmutableList.toImmutableList());

System.out.println(immutableList.getClass()); // class com.google.common.collect.RegularImmutableList

不可变集合优点

  1. 当对象被不可信的库调用时,不可变形式是安全的;

  2. 不可变对象被多个线程调用时,不存在竞态条件问题

  3. 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节);

  4. 不可变对象因为有固定不变,可以作为常量来安全使用。

新集合类型

Guava提供了许多JDK没有的集合类型。

RangeSet

RangeSet一组不相连的、非空的区间,基本实现为TreeRangeSet,看个RangeSet的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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)]

查看RangeSet的范围跨度:

1
2
3
4
5
6
7
RangeSet<Integer> rangeSet = TreeRangeSet.create();
rangeSet.add(Range.closed(1, 10));
rangeSet.add(Range.closedOpen(11, 15));

Range<Integer> span = rangeSet.span();
System.out.println(span.lowerEndpoint().intValue()); // 1
System.out.println(span.upperEndpoint().intValue()); // 15

从已有的RangeSet获取一个子范围RangeSet:

1
2
3
4
5
6
7
8
9
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 5));
numberRangeSet.add(Range.closed(5, 8));
RangeSet<Integer> numberSubRangeSet = numberRangeSet.subRangeSet(Range.closed(4, 14));

System.out.println(numberRangeSet); // [[0..2], [3..8]]
System.out.println(numberSubRangeSet); // [[4..8]]

获取除了RangeSet范围外的RangeSet:

1
2
3
4
5
6
7
8
9
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 5));
numberRangeSet.add(Range.closed(6, 8));
RangeSet<Integer> numberRangeComplementSet = numberRangeSet.complement();

System.out.println(numberRangeSet); // [[0..2], [3..5], [6..8]]
System.out.println(numberRangeComplementSet); // [(-∞..0), (2..3), (5..6), (8..+∞)]

判断一个RangeSet是否和另一个范围有交集:

1
2
3
4
5
6
7
8
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 10));
numberRangeSet.add(Range.closed(15, 18));

System.out.println(numberRangeSet); // [[0..2], [3..10], [15..18]]
System.out.println(numberRangeSet.intersects(Range.closed(4, 17))); // true

遍历RangeSet的范围区间:

1
2
3
4
5
6
7
8
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 10));
numberRangeSet.add(Range.closed(15, 18));

Set<Range<Integer>> ranges = numberRangeSet.asRanges();
ranges.forEach(System.out::print); // [0..2][3..10][15..18]

从RangeSet中获取包含某个值的访问区间:

1
2
3
4
5
6
7
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 10));
numberRangeSet.add(Range.closed(15, 18));

System.out.println(numberRangeSet.rangeContaining(7)); // [3..10]

RangeMap

RangeMap是一组不相连的、非空的区间与指定值的映射,基本实现为TreeRangeMap光这样说有点抽象,看些例子:

1
2
3
4
5
6
7
8
9
10
11
12
RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
rangeMap.put(Range.closed(1, 10), "foo");
System.out.println(rangeMap); // [[1..10]=foo]

rangeMap.put(Range.open(3, 6), "bar");
System.out.println(rangeMap); // [[1..3]=foo, (3..6)=bar, [6..10]=foo]

rangeMap.put(Range.open(10, 20), "eoo");
System.out.println(rangeMap); // [[1..3]=foo, (3..6)=bar, [6..10]=foo, (10..20)=eoo]

rangeMap.remove(Range.closed(5, 11));
System.out.println(rangeMap); // [[1..3]=foo, (3..5)=bar, (11..20)=eoo]

从RangeMap中获取一个Entry:

1
2
3
4
5
6
7
8
9
RangeMap<Integer, String> rangeMap = TreeRangeMap.create();

rangeMap.put(Range.closed(0, 2), "foo");
rangeMap.put(Range.closed(3, 5), "bar");
rangeMap.put(Range.closed(6, 8), "eoo");
Map.Entry<Range<Integer>, String> entry = rangeMap.getEntry(7);

System.out.println(entry.getKey()); // [6..8]
System.out.println(entry.getValue()); // eoo

剩下的操作和RangeSet差不多。

BiMap

BiMap是一种特殊的,双向映射的Map,可以确保不会出现重复的值并且我们总是可以安全地通过key获取到value。BiMap的基本实现为HashBiMap。

看看例子:

1
2
3
4
5
6
7
8
BiMap<String, String> biMap = HashBiMap.create();
biMap.put("k1", "v1");
biMap.put("k2", "v2");
biMap.put("k3", "v3");
System.out.println(biMap); // {k1=v1, k2=v2, k3=v3}

BiMap<String, String> inverse = biMap.inverse();
System.out.println(inverse); // {v1=k1, v2=k2, v3=k3}

通过inverse可以得到值,键映射的BiMap。

往BiMap里添加重复的值将会报错:

1
2
3
4
BiMap<String, String> biMap = HashBiMap.create();
biMap.put("k1", "v1");
biMap.put("k2", "v2");
biMap.put("k3", "v1");

QQ截图20190422172835.png

如果非要添加重复的值的话,可以用forcePut方法:

1
2
3
4
5
BiMap<String, String> biMap = HashBiMap.create();
biMap.put("k1", "v1");
biMap.put("k2", "v2");
biMap.forcePut("k3", "v1");
System.out.println(biMap); // {k2=v2, k3=v1}

Table

Table是一个包含行,列和单元格的集合类型,行和列组成有序键对。

创建一个HashBasedTable(内部使用LinkedHashMap):

1
Table<String, String, Integer> hashBasedTable = HashBasedTable.create();

如果需要对table的行和列按照自然顺序或者提供的排序规则进行排序的话,可以创建一个TreeBasedTable:

1
Table<String, String, Integer> treeBasedTable = TreeBasedTable.create();

如果事先知道行和列的值,并且table大小是固定的话,可以使用ArrayTable:

1
2
3
4
List<String> row = Lists.newArrayList("r1", "r2");
List<String> column = Lists.newArrayList("c1", "c2", "c3");
Table<String, String, Integer> arrayTable = ArrayTable.create(row, column);
System.out.println(arrayTable); // {r1={c1=null, c2=null, c3=null}, r2={c1=null, c2=null, c3=null}}

上面例子创建了一个两行三列的table。

创建不可变table:

1
2
3
Table<String, String, String> immutableTable = ImmutableTable.<String, String, String> builder()
.put("r1", "c1", "hello")
.build();

通过行和列获取单元格的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
Table<String, String, String> hashBasedTable = HashBasedTable.create();
hashBasedTable.put("r1", "c1", "hello");
hashBasedTable.put("r1", "c2", "world");
hashBasedTable.put("r2", "c1", "good");
hashBasedTable.put("r2", "c2", "bye");

System.out.println(hashBasedTable); // {r1={c1=hello, c2=world}, r2={c1=good, c2=bye}}

String v1 = hashBasedTable.get("r1", "c1");
String v2 = hashBasedTable.get("r2", "c3");

System.out.println(v1); // hello
System.out.println(v2); // null

我们可以检测table是否包含某个行键,某个列键,某个值和某个行和列组合的键:

1
2
3
4
5
6
7
8
9
10
Table<String, String, String> hashBasedTable = HashBasedTable.create();
hashBasedTable.put("r1", "c1", "hello");
hashBasedTable.put("r1", "c2", "world");
hashBasedTable.put("r2", "c1", "good");
hashBasedTable.put("r2", "c2", "bye");

boolean b1 = hashBasedTable.contains("r1", "c2"); // true
boolean b2 = hashBasedTable.containsColumn("c3"); // false
boolean b3 = hashBasedTable.containsRow("r2"); // true
boolean b4 = hashBasedTable.containsValue("world"); // true

通过行和列删除单元格,返回被删除的值:

1
2
3
4
5
6
7
8
9
10
Table<String, String, String> hashBasedTable = HashBasedTable.create();
hashBasedTable.put("r1", "c1", "hello");
hashBasedTable.put("r1", "c2", "world");
hashBasedTable.put("r2", "c1", "good");
hashBasedTable.put("r2", "c2", "bye");

String removeValue = hashBasedTable.remove("r1", "c1");

System.out.println(removeValue); // hello
System.out.println(hashBasedTable); // {r1={c2=world}, r2={c1=good, c2=bye}}

我们可以通过行或列得到一个Map,如果通过行得到Map,那么Map的键为列值,Map的值为对应单元格的值,光说有点抽象,看个例子:

1
2
3
4
5
6
7
8
9
10
11
12
Table<String, String, String> hashBasedTable = HashBasedTable.create();
hashBasedTable.put("r1", "c1", "hello");
hashBasedTable.put("r1", "c2", "world");
hashBasedTable.put("r2", "c1", "good");
hashBasedTable.put("r2", "c2", "bye");

Map<String, String> c2Map = hashBasedTable.column("c2");
Map<String, String> r1Map = hashBasedTable.row("r1");

System.out.println(c2Map); // {r1=world, r2=bye}
System.out.println(r1Map); // {c1=hello, c2=world}
System.out.println(c2Map.get("r1")); // world

我们还可以单独获取所有行或者所有列组成的Map:

1
2
3
4
5
6
7
8
9
10
11
Table<String, String, String> hashBasedTable = HashBasedTable.create();
hashBasedTable.put("r1", "c1", "hello");
hashBasedTable.put("r1", "c2", "world");
hashBasedTable.put("r2", "c1", "good");
hashBasedTable.put("r2", "c2", "bye");

Map<String, Map<String, String>> columnMap = hashBasedTable.columnMap();
Map<String, Map<String, String>> rowMap = hashBasedTable.rowMap();

System.out.println(columnMap); // {c1={r1=hello, r2=good}, c2={r1=world, r2=bye}}
System.out.println(rowMap); // {r1={c1=hello, c2=world}, r2={c1=good, c2=bye}}

获取所有行键、列键或者值的集合:

1
2
3
4
5
6
7
8
9
10
11
12
13
Table<String, String, String> hashBasedTable = HashBasedTable.create();
hashBasedTable.put("r1", "c1", "hello");
hashBasedTable.put("r1", "c2", "world");
hashBasedTable.put("r2", "c1", "good");
hashBasedTable.put("r2", "c2", "bye");

Set<String> rowKeySet = hashBasedTable.rowKeySet();
Set<String> columnKeySet = hashBasedTable.columnKeySet();
Set<Table.Cell<String, String, String>> cells = hashBasedTable.cellSet();

System.out.println(rowKeySet); // [r1, r2]
System.out.println(columnKeySet); // [c1, c2]
System.out.println(cells); // [(r1,c1)=hello, (r1,c2)=world, (r2,c1)=good, (r2,c2)=bye]

Multiset

Multiset和java.util.set类似,不过Mutiset可以添加重复的值:

1
2
3
4
5
6
7
8
9
10
11
12
HashMultiset<String> hashMultiset = HashMultiset.create();
hashMultiset.add("are you ok?");
hashMultiset.add("are you ok?");
hashMultiset.add("are you ok?");

System.out.println(hashMultiset); // [are you ok? x 3]

hashMultiset.remove("are you ok?");
System.out.println(hashMultiset); // [are you ok? x 2]

hashMultiset.setCount("are you ok?", 10); // 直接设置元素个数
System.out.println(hashMultiset); // [are you ok? x 10]

在并发环境下,我们可以使用ConcurrentHashMultiset,它的add和remove方法是线程安全的。唯一值得注意的是,在并发环境下使用setCount方法时候,需使用下面这种方式:

1
2
3
4
5
HashMultiset<String> hashMultiset = HashMultiset.create();
hashMultiset.setCount("are you ok?", 0, 5);
hashMultiset.setCount("are you ok?", 10, 5);

System.out.println(hashMultiset); // [are you ok? x 5]

第一个参数为需要添加的值,第二个参数为当前Multiset里元素个数,第三个参数为需要添加的元素个数。只有第二个参数的值正确的时候,setCount才有效,所以hashMultiset.setCount("are you ok?", 10, 5)实际上是不生效的。

Multimap

Multimap可以通过一个键映射多个值:

1
2
3
4
5
6
7
String key = "hello";
ArrayListMultimap<String, String> multimap = ArrayListMultimap.create();
multimap.put(key, "world");
multimap.put(key, "java");

System.out.println(multimap); // {hello=[world, java]}
System.out.println(multimap.get(key)); // [world, java]

ClassToInstanceMap

使用类型作为键:

1
2
3
4
5
6
7
MutableClassToInstanceMap<Object> classToInstanceMap = MutableClassToInstanceMap.create();
classToInstanceMap.put(String.class, "hello");
classToInstanceMap.put(Integer.class, 777);
classToInstanceMap.put(Double.class, 43.96);

System.out.println(classToInstanceMap); // {class java.lang.Double=43.96, class java.lang.String=hello, class java.lang.Integer=777}
System.out.println(classToInstanceMap.get(Double.class)); // 43.96

Lists、Maps&Sets

Lists

创建一个List:

1
ArrayList<String> list = Lists.newArrayList("a", "b", "c");

反转List:

1
2
3
4
ArrayList<String> list = Lists.newArrayList("a", "b", "c");

List<String> reverse = Lists.reverse(list);
System.out.println(reverse); // [c, b, a]

通过字符串生成字符集合:

1
2
List<Character> characters = Lists.charactersOf("mrbird");
System.out.println(characters); // [m, r, b, i, r, d]

将集合按照指定区块大小分区:

1
2
3
4
List<String> list = Lists.newArrayList("java", "php", "go", "python", "c#", "javascript");
List<List<String>> partition = Lists.partition(list, 2);

System.out.println(partition); // [[java, php], [go, python], [c#, javascript]]

一个删除List中重复项的技巧:

1
2
3
4
List<String> list = Lists.newArrayList("a", "p", "p", "l", "e");

ImmutableList<String> newList = ImmutableSet.copyOf(list).asList();
System.out.println(newList); // [a, p, l, e]

从集合中删除null值:

1
2
3
4
List<String> list = Lists.newArrayList("java", null," python");

Iterables.removeIf(list, Objects::isNull);
System.out.println(list); // [java, python]

Sets

通过Sets创建set:

1
Set<Object> hashSet = Sets.newHashSet();

合并两个Set:

1
2
3
4
5
Set<String> set1 = ImmutableSet.of("a", "b", "c");
Set<String> set2 = ImmutableSet.of("b", "c", "d");

Set<String> union = Sets.union(set1, set2);
System.out.println(union); // [a, b, c, d]

可以通过Sets.cartesianProduct()获取两个Set的笛卡尔积:

1
2
3
4
5
Set<Character> first = ImmutableSet.of('a', 'b');
Set<Character> second = ImmutableSet.of('c', 'd');
Set<List<Character>> result = Sets.cartesianProduct(first, second);

System.out.println(result); // [[a, c], [a, d], [b, c], [b, d]]

获取两个Set的交集:

1
2
3
4
5
Set<Character> first = ImmutableSet.of('a', 'b', 'c');
Set<Character> second = ImmutableSet.of('c', 'd', 'e');
Set<Character> intersection = Sets.intersection(first, second);

System.out.println(intersection); // [c]

获取两个Set的差集:

1
2
3
4
5
Set<Character> first = ImmutableSet.of('a', 'b', 'c');
Set<Character> second = ImmutableSet.of('c', 'd', 'e');
Set<Character> difference = Sets.symmetricDifference(first, second);

System.out.println(difference); // [a, b, d, e]

Maps

通过Maps创建Map:

1
HashMap<Object, Object> map = Maps.newHashMap();

创建期望大小的Map:

1
HashMap<Object, Object> map = Maps.newHashMapWithExpectedSize(5);

Joiner与Splitter

Joiner

Joiner用于连接操作。比如将List里的元素通过“,”连接成一个字符串:

1
2
3
4
List<String> list = Lists.newArrayList("a", "b", "c");
String join = Joiner.on(",").join(list);

System.out.println(join); // a,b,c

使用Joiner将Map转换为String:

1
2
3
4
5
6
HashMap<String, Integer> map = Maps.newHashMap();
map.put("mrbird", 18);
map.put("scott", 28);

String join = Joiner.on(",").withKeyValueSeparator("~").join(map);
System.out.println(join); // mrbird~18,scott~28

在使用Joiner的时候,如果集合中含有null值,我们可以选择跳过它:

1
2
3
4
List<String> list = Lists.newArrayList("a", null, "b", "c", "d");
String result = Joiner.on(",").skipNulls().join(list);

System.out.println(result); // a,b,c,d

或者使用指定值替代null:

1
2
3
4
List<String> list = Lists.newArrayList("a", null, "b", "c", "d");
String result = Joiner.on(",").useForNull("空").join(list);

System.out.println(result); // a,空,b,c,d

Splitter

Splitter用于将String拆分为集合类型,看个例子:

1
2
3
4
String value = "a,b,c,d      ";
List<String> list = Splitter.on(",").trimResults().splitToList(value);

System.out.println(list); // [a, b, c, d]

使用Splitter将String拆分为Map:

1
2
3
4
 String value = "mrbird=18,scott=28";
Map<String, String> map = Splitter.on(",").withKeyValueSeparator("=").split(value);

System.out.println(map); // {mrbird=18, scott=28}

分割具有多种分隔符的String:

1
2
3
4
String value = "a.b,,c,,..";
List<String> result = Splitter.onPattern("[.,]").omitEmptyStrings().splitToList(value);

System.out.println(result); // [a, b, c]

omitEmptyStrings用于忽略空字符串。

我们还可以通过指定长度来拆分字符串:

1
2
3
4
String value = "人们都说:“桂林山水甲天下”,我们乘着木船荡漾在漓江上,来观赏桂林的山水。";

List<String> list = Splitter.fixedLength(3).splitToList(value);
System.out.println(list); // [人们都, 说:“, 桂林山, 水甲天, 下”,, 我们乘, 着木船, 荡漾在, 漓江上, ,来观, 赏桂林, 的山水, 。]

也可以指定拆分项的长度:

1
2
3
4
String value = "a-b-c-d-e";
List<String> result = Splitter.on("-").limit(4).splitToList(value);

System.out.println(result); // [a, b, c, d-e]

可以看到d-e没有被拆分。

Filter&Transform

Filter

可以通过Guava提供的Predicates来实现各种集合过滤操作。

比如找出集合中包含a的元素:

1
2
3
4
List<String> list = Lists.newArrayList("java", "javascript", "c#", "golang");
Iterable<String> result = Iterables.filter(list, Predicates.containsPattern("a"));

System.out.println(result); // [java, javascript, golang]

上面的例子也可以通过Collections2.filter来实现:

1
2
3
4
List<String> list = Lists.newArrayList("java", "javascript", "c#", "golang");
Collection<String> result = Collections2.filter(list, Predicates.containsPattern("a"));

System.out.println(result);

我们也可以编写自定义的过滤规则:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 Predicate<String> predicate = new Predicate<String>() {
@Override
public boolean apply(@Nullable String input) {
return input.endsWith("a") || input.contains("#");
}
@Override
public boolean test(String input) {
return this.apply(input);
}
};
List<String> list = Lists.newArrayList("java", "javascript", "c#", "golang");
Collection<String> result = Collections2.filter(list, predicate);

System.out.println(result); // [java, c#]

组合多个过滤条件:

1
2
3
4
5
6
7
List<String> list = Lists.newArrayList("java", "javascript", "c#", "golang");
Collection<String> result = Collections2.filter(list,
Predicates.or(
Predicates.containsPattern("a"),
Predicates.containsPattern("#")
));
System.out.println(result); // [java, javascript, c#, golang]

过滤掉集合中的null:

1
2
3
4
List<String> list = Lists.newArrayList("java", null," python");
Collection<String> result = Collections2.filter(list, Predicates.<String>notNull());

System.out.println(result); // [java, python]

检测集合中是否有包含a字符的元素:

1
2
3
4
List<String> list = Lists.newArrayList("java", "c#"," python");
boolean result = Iterables.any(list, Predicates.containsPattern("a"));

System.out.println(result); // true

Transform

将集合转换为元素长度的集合:

1
2
3
4
5
6
7
8
9
10
11
Function<String, Integer> function = new Function<String, Integer>() {
@Nullable
@Override
public Integer apply(@Nullable String s) {
return s.length();
}
};
List<String> list = Lists.newArrayList("java", "c#", " python");
Iterable<Integer> result = Iterables.transform(list, function);

System.out.println(result); // [4, 2, 7]

上面的例子同样可以使用Collections2.transform来代替Iterables.transform

我们也可以通过Functions.fromPredicate来创建简单的转换函数Function:

1
2
3
4
List<String> list = Lists.newArrayList("java", "c#", " python");
Iterable<Boolean> result = Iterables.transform(list, Functions.forPredicate(Predicates.containsPattern("#")));

System.out.println(result); // [false, true, false]

组合多个转换函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Function<String, String> f1 = new Function<String, String>() {
@Override
public String apply(String input) {
return "i like " + input;
}
};

Function<String, String> f2 = new Function<String, String>() {
@Override
public String apply(String input) {
return input.toUpperCase();
}
};
List<String> list = Lists.newArrayList("java", "c#", " python");
Iterable<String> result = Iterables.transform(list, Functions.compose(f2, f1));

System.out.println(result); // [I LIKE JAVA, I LIKE C#, I LIKE PYTHON]

我们也可以将过滤和转换组合在一起使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Predicate<String> predicate = new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.startsWith("j");
}
@Override
public boolean test(String input) {
return this.apply(input);
}
};

Function<String, String> function = new Function<String,String>(){
@Override
public String apply(String input) {
return input.toUpperCase();
}
};

List<String> list = Lists.newArrayList("java", "c#", "javascript", "python");
ImmutableList<String> result = FluentIterable.from(list)
.filter(predicate)
.transform(function)
.toList();

System.out.println(result); // [JAVA, JAVASCRIPT]

Iterables

除了上面涉及的Iterables的用法外,其还提供了许多别的好用的方法。

removeAll

该方法用于从特定集合中删除给定集合中的元素:

1
2
3
4
5
6
List<String> removeFrom = Lists.newArrayList("a", "b", "c");
List<String> elementsToRemove = Lists.newArrayList("b", "c");

boolean result = Iterables.removeAll(removeFrom, elementsToRemove);
System.out.println(result); // true
System.out.println(removeFrom); // [a]

retainAll

retainAll的功能和removeAll相反:

1
2
3
4
5
6
List<String> removeFrom = Lists.newArrayList("a", "b", "c");
List<String> elementsToRetain = Lists.newArrayList("b", "c");

boolean result = Iterables.retainAll(removeFrom, elementsToRetain);
System.out.println(result); // true
System.out.println(removeFrom); // [b, c]

addAll

addAll用于将给定集合添加到现有集合中:

1
2
3
4
5
List<String> list1 = Lists.newArrayList("a", "b", "c");
List<String> list2 = Lists.newArrayList("b", "c");

boolean b = Iterables.addAll(list1, list2); // true
System.out.println(list1); // [a, b, c, b, c]

concat

concat用于合并集合,组成一个新的集合对象:

1
2
3
4
5
List<String> list1 = Lists.newArrayList("a", "b", "c");
List<String> list2 = Lists.newArrayList("b", "c");

Iterable<String> result = Iterables.concat(list1,list2);
System.out.println(result); // [a, b, c, b, c]

Iterables还包含许多别的实用方法:

QQ截图20190423231111.png

这里就不一一演示了,溜了。

QQ图片20190423231252.png

更详细的内容可以参考guava官方wiki:https://github.com/google/guava/wiki

请作者喝瓶肥宅水~

TOP