JDK提供了一系列集合類,以下所示,極大的方便了開發工做,並針對這些類提供了一個工具類java.util.Collections,Guava在此基礎上添加了一些經常使用工具類方法,相比於java.util.Collections集合類,Guava使用起來更方便快捷。本文主要介紹Guava集合工具類中Lists、Sets、Maps的常規使用。java
Lists
S.N. 方法及說明
1 List<E> asList(@Nullable E first, E[] rest)
List<E> asList(@Nullable E first, @Nullable E second, E[] rest)
將array轉化爲List,並在list頭部插入值,不支持基本類型array
2 List<List<B>> cartesianProduct(List… lists)
List<List<B>> cartesianProduct(List<? extends List<? extends B>> lists)
計算多個list笛卡爾乘積
3 ImmutableList<Character> charactersOf(String string)
List<Character> charactersOf(CharSequence sequence)
Stirng或CharSequence轉List<Character>,CharSequence接口常見實現類StringBuilder
4 ArrayList<E> newArrayList() -> 底層依賴於JDK new ArrayList()實現,JDK默認容量是10,擴容方式爲 ((舊容量 * 3) / 2) + 1
ArrayList<E> newArrayList(E… elements) -> guava首先進行容量初始化計算,計算方式爲 5L + elements數目 + (elements數目 / 10), 而後經過JDK ArrayList(int initialCapacity)初始化
ArrayList<E> newArrayList(Iterable<? extends E> elements)
ArrayList<E> newArrayList(Iterator<? extends E> elements)
初始化ArrayList
5 ArrayList<E> newArrayListWithCapacity(int initialArraySize)
初始化指定容量大小的ArrayList,其中容量指ArrayList底層依賴的數組的length屬性值,經常使用於提早知道ArrayList大小的狀況的初始化
6 ArrayList<E> newArrayListWithExpectedSize(int estimatedSize)
初始化預約容量大小的ArrayList,返回的list的實際容量爲5L + estimatedSize + (estimatedSize / 10),經常使用於不肯定ArrayList大小的狀況的初始化
7 LinkedList<E> newLinkedList()
LinkedList<E> newLinkedList(Iterable<? extends E> elements)
初始化LinkedList
8 CopyOnWriteArrayList<E> newCopyOnWriteArrayList()
CopyOnWriteArrayList<E> newCopyOnWriteArrayList(Iterable<? extends E> elements)
初始化CopyOnWriteArrayList
9 List<List<T>> partition(List<T> list, int size)
分割list,分割後每一個list的元素個數爲size
10 List<T> reverse(List<T> list)
反轉list
11 List<T> transform(List<F> fromList, Function<? super F, ? extends T> function)
轉化list,不建議使用,建議使用java8 Stream的map操做,更方便
示例代碼:數組
public class ListsTest {
@Test
public void asListTest() {
/*asList可用來將array轉化爲List,並在list頭部插入值,不支持基本類型array*/
int[] array = new int[]{1, 2, 3};
List<Integer> list = Lists.asList(4, ArrayUtils.toObject(array));
assertThat(list, contains(4, 1, 2, 3));
/*list轉array, 必須使用toArray(T[] array), 傳入的是類型徹底同樣的數組,大小爲list.size()
* 若是使用無參toArray()方法,只能轉成object[], 沒法進行類型轉換,強轉會報ClassCastException*/
Integer[] array2 = list.toArray(new Integer[list.size()]);
list = Lists.asList(8, 9, array2);
assertThat(list, contains(8, 9, 4, 1, 2, 3));
}
@Test
public void cartesianProductTest() {
/*cartesianProduct用來計算若干個List的笛卡爾乘積*/
List<Integer> list1 = Lists.newArrayList(1, 2, 3);
List<Integer> list2 = Lists.newArrayList(5, 6, 7, 8);
List<Integer> list3 = Lists.newArrayList(0, 9);
List<List<Integer>> cartesianResult = Lists.cartesianProduct(list1, list2, list3);
System.out.println(cartesianResult);
assertThat(cartesianResult, hasSize(24));
/*嵌套的List也能夠直接做爲參數計算笛卡爾乘積*/
List<List<Integer>> list = Lists.newArrayList(Lists.newArrayList(1, 2), Lists.newArrayList(5, 6));
List<List<Integer>> cartesianResult1 = Lists.cartesianProduct(list);
System.out.println(cartesianResult1);
}
@Test
public void charactersOfTest() {
/*charactersOf(String string)*/
List<Character> characters = Lists.charactersOf("zhuoli");
assertThat(characters, contains('z', 'h', 'u', 'o', 'l', 'i'));
/*charactersOf(CharSequence sequence)*/
characters = Lists.charactersOf(new StringBuilder("Michael"));
assertThat(characters, contains('M', 'i', 'c', 'h', 'a', 'e', 'l'));
}
@Test
public void newArrayListTest() {
/*無參構造函數*/
List<Integer> list = Lists.newArrayList();
assertThat(list, empty());
list = Lists.newArrayList(1, 2, 3);
assertThat(list, contains(1, 2, 3));
/*newArrayList(Iterable elements)*/
list = Lists.newArrayList(Sets.newLinkedHashSet(1, 2, 4));
assertThat(list, contains(1, 2, 4));
}
@Test
public void newArrayListWithCapacityTest() throws NoSuchFieldException, IllegalAccessException {
/*newArrayListWithCapacity直接指定返回的arrayList容量*/
List<Integer> list0 = Lists.newArrayListWithCapacity(10);
int capacity0 = getCapacity(list0);
assertEquals(10, capacity0);
/*newArrayListWithExpectedSize返回的arrayList容量爲 5L + arraySize + (arraySize / 10)*/
List<Integer> list1 = Lists.newArrayListWithExpectedSize(10);
int capacity1 = getCapacity(list1);
assertEquals(16, capacity1);
}
@Test
public void newLinkedListTest() {
List<Integer> list0 = Lists.newLinkedList();
assertThat(list0, empty());
/*newLinkedList(Iterable elements)*/
List<Integer> list1 = Lists.newLinkedList(Sets.newLinkedHashSet(3, 4, 5));
assertThat(list1, contains(3, 4, 5));
}
@Test
public void CopyOnWriteArrayListTest() {
List<Integer> list0 = Lists.newCopyOnWriteArrayList();
assertThat(list0, empty());
/*newCopyOnWriteArrayList(Iterable elements)*/
List<Integer> list1 = Lists.newCopyOnWriteArrayList(Sets.newLinkedHashSet(3, 4, 5));
assertThat(list1, contains(3, 4, 5));
}
@Test
public void partitionTest() {
List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);
List<List<Integer>> partitionList = Lists.partition(list, 2);
System.out.println(partitionList);
assertEquals(4, partitionList.size());
}
@Test
public void reverseTest() {
List<String> names = Lists.newArrayList("John", "Adam", "Jane");
List<String> reversed = Lists.reverse(names);
assertThat(reversed, contains("Jane", "Adam", "John"));
}
@Test
public void transformTest() {
/*transform用來轉化list, 建議直接使用Java8的Stream*/
List<String> list = Lists.newArrayList("this", "is", "test");
List<String> upperList = Lists.transform(list, new Function<String, String>() {
@Override
public String apply(@Nullable String s) {
return s.toUpperCase();
}
});
System.out.println(list);
List<String> upperList1 = list.stream().map(String::toUpperCase).collect(Collectors.toList());
assertEquals(upperList, upperList1);
}
@Test
public void removeDuplicatesFromList() {
/*去除list重複元素*/
List<Character> chars = Lists.newArrayList('h', 'e', 'l', 'l', 'o');
assertEquals(5, chars.size());
List<Character> result = ImmutableSet.copyOf(chars).asList();
assertThat(result, contains('h', 'e', 'l', 'o'));
/*經過Java8 Stream去除重複元素, 建議使用*/
chars = chars.stream().distinct().collect(Collectors.toList());
assertEquals(result, chars);
}
/*經過反射獲取list內部實現elementData的length屬性*/
private int getCapacity(List<Integer> list) throws NoSuchFieldException, IllegalAccessException {
Field f = ArrayList.class.getDeclaredField("elementData");
f.setAccessible(true);
Object[] elementData = (Object[]) f.get(list);
return elementData.length;
}
}
Sets
S.N. 方法及說明
1 Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets)
Set<List<B>> cartesianProduct(Set… sets)
求多個Set的笛卡爾乘積
2 Set<Set<E>> combinations(Set<E> set, final int size)
求Set的size組合,數學上的公式爲 n! / r! * (n – r)!
3 Sets.SetView<E> difference(final Set<E> set1, final Set<?> set2)
求set1與set2的差集,返回的是一個Set視圖,不支持插入和刪除操做
4 Sets.SetView<E> intersection(final Set<E> set1, final Set<?> set2)
求set1與set2的交集,返回的是一個Set視圖,不支持插入和刪除操做
5 Set<E> newConcurrentHashSet()
Set<E> newConcurrentHashSet(Iterable<? extends E> elements)
ConcurrentHashSet初始化
6 CopyOnWriteArraySet<E> newCopyOnWriteArraySet()
CopyOnWriteArraySet<E> newCopyOnWriteArraySet(Iterable<? extends E> elements)
CopyOnWriteArraySet初始化
7 HashSet<E> newHashSet()
HashSet<E> newHashSet(E… elements)
HashSet<E> newHashSet(Iterable<? extends E> elements)
HashSet<E> newHashSet(Iterator<? extends E> elements)
HashSet初始化
8 LinkedHashSet<E> newLinkedHashSet()
LinkedHashSet<E> newLinkedHashSet(Iterable<? extends E> elements)
LinkedHashSet初始化
9 HashSet<E> newHashSetWithExpectedSize(int expectedSize)
初始化一個存在初始容量的HashSet,HashSet底層依賴於HashMap,expectedSize用於肯定HashMap底層bucket數組的初始化容量(bucket數組容量總爲2的指數冪),好比expectedSize爲14,其實底層bucket數組初始化容量爲16(大於14的最小2的指數冪)
10 LinkedHashSet<E> newLinkedHashSetWithExpectedSize(int expectedSize)
初始化一個存在初始容量的LinkedHashSet,原理同上
11 TreeSet<E> newTreeSet()
TreeSet<E> newTreeSet(Comparator<? super E> comparator)
TreeSet<E> newTreeSet(Iterable<? extends E> elements)
初始化TreeSet
12 Sets.SetView<E> union(final Set<? extends E> set1, final Set<? extends E> set2)
求set1和set2對的並集
13 Set<E> filter(Set<E> unfiltered, com.google.common.base.Predicate<? super E> predicate)
Set過濾
SortedSet<E> filter(SortedSet<E> unfiltered, com.google.common.base.Predicate<? super E> predicate)
SortedSet(如LinkedHashSet)過濾
NavigableSet<E> filter(NavigableSet<E> unfiltered, com.google.common.base.Predicate<? super E> predicate)
NavigableSet(如TreeSet)過濾
也可使用java8的Stream fielter操做,也很是方便 java8 Stream的map操做
示例代碼:app
public class SetsTest {
@Test
public void cartesianProductTest() {
List<Set<Integer>> setList = Lists.newArrayList();
setList.add(Sets.newHashSet(1, 2));
setList.add(Sets.newHashSet(3, 6, 7));
Set<List<Integer>> result = Sets.cartesianProduct(setList);
System.out.println(result);
assertEquals(6, result.size());
}
@Test
public void cartesianProductTest1() {
Set<Integer> set1 = Sets.newHashSet(1, 2);
Set<Integer> set2 = Sets.newHashSet(3, 6, 7);
Set<List<Integer>> result = Sets.cartesianProduct(set1, set2);
System.out.println(result);
assertEquals(6, result.size());
}
@Test
public void combinationsTest() {
/*求組合結果 n! / r! * (n - r)!*/
Set<Integer> set = Sets.newHashSet(1, 2, 3, 4, 5);
Set<Set<Integer>> result = Sets.combinations(set, 2);
result.forEach(System.out::println);
assertEquals(10, result.size());
}
@Test
public void differenceTest() {
/*求差集,返回結果Set是一個視圖,不支持插入、刪除操做*/
Set<Character> first = Sets.newHashSet('a', 'b', 'c');
Set<Character> second = Sets.newHashSet('b', 'c', 'd');
Set<Character> result = Sets.difference(first, second);
System.out.println(result);
result = Sets.difference(second, first);
System.out.println(result);
}
@Test
public void filterTest() {
Set<Integer> set0 = Sets.newHashSet(1, 2, 3, 4, 5, 6);
Set<Integer> filterResult0 = Sets.filter(set0, ele -> ele % 2 == 0);
assertThat(filterResult0, containsInAnyOrder(2, 4, 6));
Set<Integer> set1 = Sets.newLinkedHashSet(Lists.newArrayList(1, 2, 3, 4, 5, 6));
Set<Integer> filterResult1 = Sets.filter(set1, ele -> ele % 2 == 1);
assertThat(filterResult1, contains(1, 3, 5));
Set<Integer> set2 = Sets.newTreeSet(Lists.newArrayList(1, 2, 3, 4, 5, 6));
Set<Integer> filterResult2 = Sets.filter(set2, ele -> ele % 2 == 1);
assertThat(filterResult2, contains(1, 3, 5));
}
@Test
public void intersectionTest() {
/*求交集,返回結果Set是一個視圖,不支持插入、刪除操做*/
Set<Character> first = ImmutableSet.of('a', 'b', 'c');
Set<Character> second = ImmutableSet.of('b', 'c', 'd');
Set<Character> intersection = Sets.intersection(first, second);
assertThat(intersection, containsInAnyOrder('b', 'c'));
}
@Test
public void newConcurrentHashSetTest() {
Set<Integer> set = Sets.newConcurrentHashSet();
assertTrue(set.isEmpty());
set = Sets.newConcurrentHashSet(Lists.newArrayList(1, 2, 3));
assertThat(set, containsInAnyOrder(1, 2, 3));
}
@Test
public void newCopyOnWriteArraySetTest() {
Set<Integer> set = Sets.newCopyOnWriteArraySet();
assertTrue(set.isEmpty());
set = Sets.newCopyOnWriteArraySet(Lists.newArrayList(1, 2, 3));
assertThat(set, containsInAnyOrder(1, 2, 3));
}
@Test
public void newHashSetTest() {
/*HashSet構造方法*/
Set<Integer> set = Sets.newHashSet();
assertTrue(set.isEmpty());
set = Sets.newHashSet(1, 2, 3);
assertThat(set, containsInAnyOrder(1, 2, 3));
set = Sets.newHashSet(Lists.newArrayList(4, 5, 6));
assertThat(set, containsInAnyOrder(4, 5, 6));
set = Sets.newHashSet(Lists.newArrayList(0, 9, 8).iterator());
assertThat(set, containsInAnyOrder(0, 9, 8));
}
@Test
public void newHashSetWithExpectedSizeTest() {
/*Set底層依賴於Map實現,newHashSetWithExpectedSize傳入的數值爲Map底層bucket數組大小,JDK實現爲2的指數冪,因此下面代碼底層Map的bucket數組實際大小爲16*/
Set<Integer> set = Sets.newHashSetWithExpectedSize(14);
assertTrue(set.isEmpty());
}
@Test
public void newLinkedHashSetTest() {
/*HashSet構造方法*/
Set<Integer> set = Sets.newLinkedHashSet();
assertTrue(set.isEmpty());
set = Sets.newLinkedHashSet(Lists.newArrayList(1, 2, 3));
assertThat(set, containsInAnyOrder(1, 2, 3));
}
@Test
public void newLinkedHashSetWithExpectedSizeTest() {
/*Set底層依賴於Map實現,newLinkedHashSetWithExpectedSize傳入的數值爲Map底層bucket數組大小,JDK實現爲2的指數冪,因此下面代碼底層Map的bucket數組實際大小爲16*/
Set<Integer> set = Sets.newLinkedHashSetWithExpectedSize(14);
assertTrue(set.isEmpty());
}
@Test
public void newTreeSetTest() {
Set<Integer> set = Sets.newTreeSet();
assertTrue(set.isEmpty());
set = Sets.newTreeSet(Lists.newArrayList(1, 2, 3));
assertThat(set, containsInAnyOrder(1, 2, 3));
}
@Test
public void unionTest() {
/*求並集*/
Set<Character> first = ImmutableSet.of('a', 'b', 'c');
Set<Character> second = ImmutableSet.of('b', 'c', 'd');
Set<Character> intersection = Sets.union(first, second);
assertThat(intersection, containsInAnyOrder('a', 'b', 'c', 'd'));
}
}
Maps
S.N. 方法及說明
1 Map<K, V> asMap(Set<K> set, Function<? super K, V> function)
SortedMap<K, V> asMap(SortedSet<K> set, Function<? super K, V> function)
NavigableMap<K, V> asMap(NavigableSet<K> set, Function<? super K, V> function)
Set轉Map,函數式接口用於經過Set的元素值獲取Map的value值
2 MapDifference<K, V> difference(Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right)
SortedMapDifference<K, V> difference(SortedMap<K, ? extends V> left, Map<? extends K, ? extends V> right)
經過Map的key計算left和right的差值,MapDifference包含 left – right、right – left及left與right相交這三部分信息
3 BiMap<K, V> filterEntries(BiMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate)
Map<K, V> filterEntries(Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate)
SortedMap<K, V> filterEntries(SortedMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate)
NavigableMap<K, V> filterEntries(NavigableMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate)
經過Map的Entry(key和value)過濾Map,函數式接口爲經過Entry產生的過濾條件
4 BiMap<K, V> filterKeys(BiMap<K, V> unfiltered, Predicate<? super K> keyPredicate)
Map<K, V> filterKeys(Map<K, V> unfiltered, Predicate<? super K> keyPredicate)
SortedMap<K, V> filterKeys(SortedMap<K, V> unfiltered, Predicate<? super K> keyPredicate)
NavigableMap<K, V> filterKeys(NavigableMap<K, V> unfiltered, Predicate<? super K> keyPredicate)
經過Map的key過濾Map,函數式接口爲經過key產生的過濾條件
5 BiMap<K, V> filterValues(BiMap<K, V> unfiltered, Predicate<? super V> valuePredicate)
Map<K, V> filterValues(Map<K, V> unfiltered, Predicate<? super V> valuePredicate)
SortedMap<K, V> filterValues(SortedMap<K, V> unfiltered, Predicate<? super V> valuePredicate)
NavigableMap<K, V> filterValues(NavigableMap<K, V> unfiltered, Predicate<? super V> valuePredicate)
經過Map的value過濾Map,函數式接口爲經過value產生的過濾條件
6 ImmutableMap<String, String> fromProperties(Properties properties)
經過Properties構造ImmutableMap
7 ConcurrentMap<K, V> newConcurrentMap()
構造ConCurrentHashMap
8 HashMap<K, V> newHashMap()
HashMap<K, V> newHashMap(Map<? extends K, ? extends V> map)
構造HashMap
9 LinkedHashMap<K, V> newLinkedHashMap()
LinkedHashMap<K, V> newLinkedHashMap(Map<? extends K, ? extends V> map)
構造LinkedHashMap
10 HashMap<K, V> newHashMapWithExpectedSize(int expectedSize)
LinkedHashMap<K, V> newLinkedHashMapWithExpectedSize(int expectedSize)
初始化必定大小的HashMap/LinkedHashMap,expectedSize用於肯定HashMap底層bucket數組長度,bucket數組長度爲2的指數冪,若是expectedSize上送14,其實底層bucket數組長度爲16
11 TreeMap<K, V> newTreeMap()
newTreeMap(SortedMap<K, ? extends V> map)
TreeMap<K, V> newTreeMap(@Nullable Comparator<C> comparator)
構造TreeMap
12 NavigableMap<K, V> subMap(NavigableMap<K, V> map, Range<K> range)
經過Range肯定的key的範圍分割Map,即求子Map
13 ImmutableMap<K, V> toMap(Iterable<K> keys, Function<? super K, V> valueFunction)
ImmutableMap<K, V> toMap(Iterator<K> keys, Function<? super K, V> valueFunction)
list轉Map,函數式接口用於經過list元素肯定Map的value,若是list中存在重複元素,會丟棄重複元素,不會拋異常,經過Java8 Stream操做會拋IllegalStateException異常
14 Map<K, V2> transformEntries(Map<K, V1> fromMap, Maps.EntryTransformer<? super K, ? super V1, V2> transformer)
SortedMap<K, V2> transformEntries(SortedMap<K, V1> fromMap, Maps.EntryTransformer<? super K, ? super V1, V2> transformer)
NavigableMap<K, V2> transformEntries(NavigableMap<K, V1> fromMap, Maps.EntryTransformer<? super K, ? super V1, V2> transformer)
經過Map的Entry(key和value)轉化Map,函數式表達式用於經過Entry肯定轉化後的value值
15 Map<K, V2> transformValues(Map<K, V1> fromMap, Function<? super V1, V2> function)
SortedMap<K, V2> transformValues(SortedMap<K, V1> fromMap, Function<? super V1, V2> function)
NavigableMap<K, V2> transformValues(NavigableMap<K, V1> fromMap, Function<? super V1, V2> function)
經過Map的value轉化Map,函數式接口用於經過value肯定轉化後的value值
16 ImmutableMap<K, V> uniqueIndex(Iterable<V> values, Function<? super V, K> keyFunction)
ImmutableMap<K, V> uniqueIndex(Iterator<V> values, Function<? super V, K> keyFunction)
List元素做爲Map的value,函數式接口用於經過List元素肯定Map的key,若是生成的key存在重複的狀況,會拋IllegalArgumentException異常,經過Java8 Stream操做會拋IllegalStateException異常
示例代碼:ide
public class MapsTest {
@Test
public void asMapTest() {
/*asSet可用來將Set、SortedSet、NavigableSet轉Map*/
Map<String, Integer> compareMap = Maps.newHashMap();
compareMap.put("This", 4);
compareMap.put("is", 2);
compareMap.put("test", 4);
Set<String> hashSet = Sets.newHashSet(Lists.newArrayList("This", "is", "test"));
Map<String, Integer> map0 = Maps.asMap(hashSet, String::length);
assertThat(map0, is(compareMap));
Set<String> treeSet = Sets.newTreeSet("This", "is", "test");
Map<String, Integer> map1 = Maps.asMap(treeSet, String::length);
assertThat(map1, equalTo(map0));
Set<String> sortedSet = Sets.newLinkedHashSet("This", "is", "test");
Map<String, Integer> map2 = Maps.asMap(sortedSet, String::length);
assertThat(map2, is(map1));
/*經過java8 Stream 也能夠實現*/
Map<String, Integer> map3 = sortedSet.stream().collect(Collectors.toMap(ele -> ele, String::length));
assertThat(map3, is(map2));
}
@Test
public void differenceTest() {
Map<String, Integer> left = Maps.newHashMap();
Map<String, Integer> right = Maps.newHashMap();
left.put("Michael", 18);
left.put("Jane", 20);
left.put("Mary", 22);
left.put("haha", 22);
right.put("Michael", 19);
right.put("Jane", 18);
right.put("Mary", 22);
right.put("zhuoli", 23);
/*left與right的差*/
MapDifference<String, Integer> difference = Maps.difference(left, right);
/*left - right {haha=22}*/
Map<String, Integer> entriesOnlyOnLeft = difference.entriesOnlyOnLeft();
System.out.println(entriesOnlyOnLeft);
/*right - left {zhuoli=23}*/
Map<String, Integer> entriesOnlyOnRight = difference.entriesOnlyOnRight();
System.out.println(entriesOnlyOnRight);
/*left與right相同的Entry {Mary=22}*/
Map<String, Integer> entriesInCommon = difference.entriesInCommon();
System.out.println(entriesInCommon);
}
@Test
public void filterEntriesTest() {
/*根據Entry過濾Map*/
Map<String, Integer> compareMap = Maps.newHashMap();
compareMap.put("Jane", 20);
compareMap.put("Mary", 22);
Map<String, Integer> left = Maps.newHashMap();
left.put("Michael", 18);
left.put("Jane", 20);
left.put("Mary", 22);
Map<String, Integer> resultMap = Maps.filterEntries(left, ele -> ele.getValue() > 18);
assertThat(resultMap, is(compareMap));
/*Java8 Stream filter也能夠,比較起來好像Guava的Maps更方便一些*/
Map<String, Integer> streamResult = left.entrySet().stream().filter(ele -> ele.getValue() > 18).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
assertThat(streamResult, is(resultMap));
}
@Test
public void filterKeysTest() {
/*根據key過濾Map*/
Map<String, Integer> compareMap = Maps.newHashMap();
compareMap.put("Michael", 18);
Map<String, Integer> left = Maps.newHashMap();
left.put("Michael", 18);
left.put("Jane", 20);
left.put("Mary", 22);
Map<String, Integer> resultMap = Maps.filterKeys(left, ele -> ele.length() > 4);
assertThat(resultMap, is(compareMap));
/*Java8 Stream filter也能夠,比較起來好像Guava的Maps更方便一些*/
Map<String, Integer> streamResult = left.entrySet().stream().filter(ele -> ele.getKey().length() > 4).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
assertThat(streamResult, is(resultMap));
}
@Test
public void filterValuesTest() {
/*根據value過濾Map*/
Map<String, Integer> compareMap = Maps.newHashMap();
compareMap.put("Michael", 18);
Map<String, Integer> left = Maps.newHashMap();
left.put("Michael", 18);
left.put("Jane", 20);
left.put("Mary", 22);
Map<String, Integer> resultMap = Maps.filterValues(left, ele -> ele < 20);
assertThat(resultMap, is(compareMap));
/*Java8 Stream filter也能夠,比較起來好像Guava的Maps更方便一些*/
Map<String, Integer> streamResult = left.entrySet().stream().filter(ele -> ele.getValue() < 20).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
assertThat(streamResult, is(resultMap));
}
@Test
public void fromPropertiesTest() {
/*經過Properties構造ImmutableMap*/
Map<String, String> compareMap = Maps.newHashMap();
compareMap.put("this", "1");
compareMap.put("is", "2");
compareMap.put("test", "3");
Properties properties = new Properties();
/*注意Properties的value必須也爲String, 不然會報NPE,詳見Properties的getProperty方法(getProperty獲取value爲null,
ImmutableMap.Builder put操做中ImmutableMap.entryOf操做會checkEntryNotNull,報NPE)*/
properties.put("this", "1");
properties.put("is", "2");
properties.put("test", "3");
/*fromProperties生成的是ImmutableMap<String, String>*/
Map<String, String> map = Maps.fromProperties(properties);
assertThat(map, is(compareMap));
}
@Test
public void newConcurrentMapTest() {
Map<String, Integer> map = Maps.newConcurrentMap();
assertTrue(map.isEmpty());
}
@Test
public void newHashMapTest() {
Map<String, Integer> map = Maps.newHashMap();
assertTrue(map.isEmpty());
Map<String, Integer> sortedMap = Maps.newLinkedHashMap();
sortedMap.put("zhuoli", 11);
/*HashMap<K, V> newHashMap(Map<? extends K, ? extends V> map)*/
Map<String, Integer> map1 = Maps.newHashMap(sortedMap);
assertThat(map1, hasEntry("zhuoli", 11));
}
@Test
public void newHashMapWithExpectedSizeTest() {
/*傳入的數值爲Map底層bucket數組大小,JDK實現爲2的指數冪,因此下面代碼底層Map的bucket數組實際大小爲16*/
Map<String, Integer> map = Maps.newHashMapWithExpectedSize(14);
assertTrue(map.isEmpty());
}
@Test
public void newLinkedHashMapTest() {
Map<String, Integer> map = Maps.newLinkedHashMap();
assertTrue(map.isEmpty());
Map<String, Integer> sortedMap = Maps.newLinkedHashMap();
sortedMap.put("zhuoli", 11);
/*LinkedHashMap<K, V> newLinkedHashMap(Map<? extends K, ? extends V> map)*/
Map<String, Integer> map1 = Maps.newLinkedHashMap(sortedMap);
assertThat(map1, hasEntry("zhuoli", 11));
}
@Test
public void newLinkedHashMapWithExpectedSizeTest() {
/*傳入的數值爲Map底層bucket數組大小,JDK實現爲2的指數冪,因此下面代碼底層Map的bucket數組實際大小爲16*/
Map<String, Integer> map = Maps.newLinkedHashMapWithExpectedSize(14);
assertTrue(map.isEmpty());
}
@Test
public void newTreeMapTest() {
Map<String, Integer> map = Maps.newTreeMap();
assertTrue(map.isEmpty());
TreeMap<String, Integer> sortedMap = Maps.newTreeMap();
sortedMap.put("zhuoli", 11);
Map<String, Integer> map1 = Maps.newTreeMap(sortedMap);
assertThat(map1, hasEntry("zhuoli", 11));
}
@Test
public void subMapTest() {
Map<Integer, String> compareMap = Maps.newHashMap();
compareMap.put(1, "chenhao");
compareMap.put(2, "zhuoli");
TreeMap<Integer, String> idNameMap = Maps.newTreeMap();
idNameMap.put(1, "chenhao");
idNameMap.put(2, "zhuoli");
idNameMap.put(3, "xiaoxian");
idNameMap.put(4, "haha");
/*定義子Map的key的範圍爲(0, 3)*/
Range<Integer> range = Range.open(0, 3);
Map<Integer, String> result = Maps.subMap(idNameMap, range);
assertThat(result, is(compareMap));
}
@Test
public void toMapTest() {
Map<String, String> compareMap = Maps.newHashMap();
compareMap.put("this", "THIS");
compareMap.put("is", "IS");
compareMap.put("test", "TEST");
List<String> list = Lists.newArrayList("this", "is", "test", "is");
/*ImmutableMap<K, V> toMap(Iterable<K> keys, Function<? super K, V> valueFunction)
* 第二個參數爲用於獲取map value的函數表達式*/
/*Guava toMap若是Iterable集合存在重複的狀況,不會拋異常,會丟棄重複值*/
Map<String, String> map = Maps.toMap(list, String::toUpperCase);
System.out.println(map);
assertThat(map, equalTo(compareMap));
/*Java 8 stream toMap操做*/
/*使用Java8 stream toMap操做時,若是key存在重複的狀況,會拋異常IllegalStateException*/
assertThatThrownBy(() -> list.stream().collect(Collectors.toMap(ele -> ele, String::toUpperCase)))
.isInstanceOf(IllegalStateException.class)
.hasNoCause();
}
@Test
public void transformEntriesTest() {
/*根據Entry轉化Map(根據key和value修改Map的value值)*/
Map<String, String> compareMap = Maps.newHashMap();
compareMap.put("this", "this4");
compareMap.put("is", "is2");
compareMap.put("test", "test4");
Map<String, Integer> map = Maps.newHashMap();
map.put("this", 4);
map.put("is", 2);
map.put("test", 4);
Map<String, String> resultMap = Maps.transformEntries(map, (k, v) -> k + v.toString());
assertThat(resultMap, equalTo(compareMap));
Map<String, Integer> resultMap1 = Maps.transformEntries(map, (k, v) -> v + 1);
assertThat(resultMap1, hasEntry("this", 5));
/*Java 8 Stream Collectors.toMap轉化Map, Guava使用簡單一些,可是Java8適用性更強,能夠同時轉化key和value*/
Map<String, String> resultMap2 = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, ele -> ele.getKey() + ele.getValue()));
assertThat(resultMap2, equalTo(compareMap));
Map<String, String> resultMap3 = map.entrySet().stream().collect(Collectors.toMap(ele -> ele.getKey().toUpperCase(), ele -> ele.getKey() + ele.getValue()));
assertThat(resultMap3, hasEntry("THIS", "this4"));
}
@Test
public void transformValuesTest(){
/*經過Map的value轉化Map(根據value修改value值)*/
Map<String, Integer> compareMap = Maps.newHashMap();
compareMap.put("this", 5);
compareMap.put("is", 3);
compareMap.put("test", 5);
Map<String, Integer> map = Maps.newHashMap();
map.put("this", 4);
map.put("is", 2);
map.put("test", 4);
Map<String, Integer> resultMap = Maps.transformValues(map, value -> value + 1);
assertThat(resultMap, is(compareMap));
/*Java8 Stream 操做*/
Map<String, Integer> resultMap1 = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, ele -> ele.getValue() + 1));
assertThat(resultMap1, is(compareMap));
}
@Test
public void uniqueIndexTest(){
Map<Integer, String> compareMap = Maps.newHashMap();
compareMap.put(4, "this");
compareMap.put(2, "is");
/*Iterable做爲Map的value,經過函數表達式生成key組成map*/
List<String> list = Lists.newArrayList("this", "is");
Map<Integer, String> map = Maps.uniqueIndex(list, String::length);
assertThat(map, is(compareMap));
/*若是函數式表達式生成的key存在重複的狀況,會拋IllegalArgumentException異常*/
List<String> list1 = Lists.newArrayList("this", "is", "test");
assertThatThrownBy(()->Maps.uniqueIndex(list1, String::length))
.isInstanceOf(IllegalArgumentException.class)
.hasNoCause();
/*uniqueIndex Java8 Stream等價操做*/
Map<Integer, String> map1 = list.stream().collect(Collectors.toMap(String::length, ele -> ele));
assertThat(map1, is(compareMap));
/*Java8 key重複會拋IllegalStateException異常*/
assertThatThrownBy(()->list1.stream().collect(Collectors.toMap(String::length, ele -> ele)))
.isInstanceOf(IllegalStateException.class)
.hasNoCause();
}
}
以上能夠發現,Guava Maps中的複雜操做如asMap(set轉map)、filterEntries/filterKeys/filterValues(fiter過濾)、toMap(list轉map)、transformEntries/transformValues(轉化map)、uniqueIndex(list元素做爲value轉map)等均可以經過Java8的Stream操做實現。Java8的Stream操做適用性比較廣,可是有時候須要書寫較長的鏈式操做,Guava針對各個場景提供了具體的方法。其實本質上沒什麼區別,就看你們在開發中怎麼選擇了。函數
測試代碼:碼雲 – 卓立 – Guava測試代碼工具
Google Guava Docs
Google Guava User Guide
Guava源碼
---------------------
版權聲明:本文爲CSDN博主「卓立0」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。
原文連接:https://blog.csdn.net/weixin_41835612/article/details/83646257測試