This is the 22nd day of my participation in the August More Text Challenge

Introduction to the use of Google Guava Collections

Introduction to the

Google Guava Collections is an open source project that enhances and extends the Java Collections Framework. It is highly regarded in the Java community for its high quality API implementation and full use of Java features. The author mainly introduces its basic usage and function characteristics.

Used to introduce

  • Google Guava Collections (hereafter referred to simply as Guava Collections) is an enhancement and extension of the Java Collections Framework. Every Java developer uses a variety of data structures in their work, and in many cases the Java Collections Framework can help you do this.

  • However, in those cases where you use the Java Collections Framework apis but still need to write a lot of code to implement some complex logic, you can try Guava Collections to help you do this. These high-quality apis make your code shorter, easier to read and modify, and easier to work with.

The target readers

  • To understand Java open source tools, the reader of this article should have at least a basic knowledge of Java, especially the features of JDK5.
  • Because Guava Collections make full use of stereotypes, loops enhance such features. As an enhancement to the Java Collections Framework, the reader must have a clear understanding of the Java Collections Framework, including the main interface conventions and commonly used implementation classes.
  • Moreover, Guava Collections largely help developers to complete the operation of relatively complex data structures, so the basic knowledge of data structures and algorithms is also a necessary condition for a clear understanding of Guava Collections.

Project background

  • Guava Collections was code written by Google engineers Kevin Bourrillion and Jared Levy in their famous “20%” time. Of course there are other developers who contribute code as an open source project.

  • Joshua Bloch, author of the Java Collections Framework, also participated in the code review and made suggestions during the writing process.

  • It has been moved to another open source project called Guava-Libraries for maintenance. Because it has similar features and is an open source project, it is natural to compare it to the Apache Commons Collections.


The collection is introduced

  • Immutable Collections: still use Collections. UnmodifiableXXX ()? Immutable Collections This is the true unmodifiable collection l Multiset: see how to put repeating elements into a collection.

  • Multimaps: It is cumbersome to write an implementation by Multimaps when one key corresponds to multiple values

  • BiMap: java.util.Map only ensures that keys are not duplicated. BiMap also ensures that values are not duplicated

  • MapMaker: Super powerful Map constructor class

  • Ordering Class: When Ordering a set, you can use the Comparator to order the set, but Ordering class can simplify the Ordering code


Immutable Collections: Truly Immutable Collections
  • Everyone used Collections. UnmodifiableXXX () to make a collection of immutable. Let’s say you want to construct a Set that stores constants.
Set<String> set = new HashSet<String>(Arrays.asList(new String[]{"RED"."GREEN"})); 
Set<String> unmodifiableSet = Collections.unmodifiableSet(set);
Copy the code
  • Every time the unmodifiableSet. The add () throws an UnsupportedOperationException.

  • What happens if someone adds or removes elements to the original set? Result unmodifiableSet is also added or removed.

Constructing such a simple set took two sentences of code. Here’s how ImmutableSet can be made more secure and concise:

ImmutableSet<String> immutableSet = ImmutableSet.of("RED"."GREEN");
Copy the code
  • * * and try to adjust the add method, it will throw an UnsupportedOperationException, important is the increasing the readability of the code, very intuitively show the purpose of the code. What if this code protects a set like before?
ImmutableSet<String> immutableSet = ImmutableSet.copyOf(set);
Copy the code

In terms of construction, the ImmutableSet collection also provides the Builder mode to construct a collection: in this case, the Builder can add not only individual elements but also existing collections.

Builder<String> builder = ImmutableSet.builder(); 
ImmutableSet<String> immutableSet = builder.add("RED").addAll(set).build();
Copy the code

Guava Collections also provide various implementations of Immutable Collections

  • ImmutableList

  • ImmutableSet

 ImmutableSet.of(4.8.15.16.23.42);
 ImmutableSet.copyOf(numbers);
Copy the code
  • ImmutableSortedSet
  • ImmutableMap
public static final ImmutableMap<String, Integer>
 ENGLISH_TO_INT = ImmutableMap
 .with("four".4)
 .with("eight".8)
 .with("fifteen".15)
 .with("sixteen".16)
 .with("twenty-three".23)
 .with("forty-two".42)
 .build();

ImmutableMap.of(1."one".2."two");
Copy the code
  • ImmutableSortedMap (one day)

Multiset: To put repeating elements into a collection
  • You might say this conflicts with the contract of the Set interface, because the JavaDoc of the Set interface states that duplicate elements cannot be put in. In fact, Multiset doesn’t implement the java.util.Set interface, it’s more like a Bag. A normal Set would look like this :[car, ship, bike], whereas a Multiset would look like this:

[Car x 2, ship x 6, bike x 3]

  • For example, if you have a List of various strings, and you want to count the number of occurrences of each string in the List:
Map<String, Integer> map = new HashMap<String, Integer>(); 
for(String word : wordList){ 
   Integer count = map.get(word); 
   map.put(word, (count == null)?1 : count + 1); 
}
//count word "the" Integer count = map.get(" the ");
Copy the code
If we use Multiset we can do this:
HashMultiset<String> multiSet = HashMultiset.create();
multiSet.addAll(wordList); 
//count word "the" Integer count = multiset. count(" the ");
Copy the code
  • This eliminates the need for loops, and the Multiset method is called count, which is much more readable than calling GET in a Map.

  • Multiset also provides methods such as setCount to set the number of repetitions of elements. Although you can do something similar with Map, Multiset is much less readable than Multiset.

Common classes that implement the Multiset interface are:
  • HashMultiset: The element is stored in the HashMap
  • LinkedHashMultiset: Elements are stored in the LinkedHashMap, where the order of elements is determined by the order in which they were first placed
  • TreeMultiset: Elements are sorted and stored in TreeMap
  • EnumMultiset: The element must be of enum type
  • ImmutableMultiset: A Mutiset that cannot be modified
  • Looking at this, you may have noticed that Guava Collections construct objects using static methods like create or of. That’s because of these sets
  • Most classes have private constructors for multiple arguments, which can be difficult for guest code programmers to use because of the large number of arguments. And in this way it can
  • Returns an object of a subtype of the original type. In addition, this approach is much cleaner for creating generic objects.

Looking at this, you may have noticed that Guava Collections construct objects using static methods like create or of. This is because most of these collection classes have private constructors for multiple arguments, which can be difficult for guest code programmers to use because of the large number of arguments. And in this way it can

Returns an object of a subtype of the original type. In addition, this approach is much cleaner for creating generic objects.

Multimap: Puts multiple elements inside the value of a Map

A Multimap is a data structure in which a key corresponds to multiple values. It looks a lot like the java.util.Map structure, but Muitimap is not a Map and has no interface to implement it. Imagine you call Map twice with the same put method as key. The result is value overwriting the second time

Value of the first time. But for Muitimap, this key corresponds to two values. So the Map looks like this: {k1=v1, k2=v2… }, and Muitimap is: {k1 = (v1, v2, v3), k2 = [v7 and v8],… }.

  • For example, by secret ballot, all ballots are placed in a List, and each element of the List contains the names of the voters and electors.

We can write this:

//Key is candidate name, its value is his voters 
HashMap<String, HashSet<String>> hMap = new HashMap<String, HashSet<String>>(); 
for(Ticket ticket: tickets){ 
HashSet<String> set = hMap.get(ticket.getCandidate()); 
if(set == null){ 
 set = new HashSet<String>(); 
 hMap.put(ticket.getCandidate(), set); 
} 
set.add(ticket.getVoter());
}
Copy the code

Let’s see what Muitimap can do:

HashMultimap<String, String> map = HashMultimap.create(); 
for(Ticket ticket: tickets){ 
map.put(ticket.getCandidate(), ticket.getVoter()); 
}
Copy the code

It’s that simple! The main implementation classes of the Muitimap interface are:

  • HashMultimap: A key is placed in a HashMap and a value in a HashSet. That is, the value of a key cannot be repeated
  • ArrayListMultimap: The key is placed in the HashMap and the value in the ArrayList, that is, the corresponding value of a key can be repeated in order
  • LinkedHashMultimap: The key is placed in the LinkedHashMap and the value is placed in the LinkedHashSet. That is, the value of a key is in an order that cannot be repeated
  • TreeMultimap: The key is placed in the TreeMap and the value is placed in the TreeSet. That is, the value corresponding to a key has an order
  • ImmutableMultimap: A Multimap that cannot be modified
BiMap: two-way Map

**BiMap implements the java.util.map interface. In other words, the key and value are equivalent. If you put a duplicate element inside a BiMap value, you will get an IllegalArgumentException. 六四屠杀

For example, you may often encounter logic that reverses the key value of a Map based on its value:

for(Map.Entry<User, Address> entry : map.entreSet()){ 
if(entry.getValue().equals(anAddess)){ 
 returnentry.getKey(); }}return null;
Copy the code
  • If you put both User and Address in BiMap, one line of code results: return bimap.inverse ().get(anAddess);
  • The inverse method here is to swap the key set value set of BiMap, so BiMap == bimap.inverse ().inverse().
Common implementations of BiMap are:
  • HashBiMap: Both key and value collections have HashMap implementations
  • EnumBiMap: The key and value must be of the enum type
  • ImmutableBiMap: Unmodifiable BiMap

MapMaker: Super powerful Map builder

MapMaker is the utility class used to construct ConcurrentMap.

Why is MapMaker super powerful? Take a look at the following examples. First, it can be used to construct ConcurrentHashMap:

//ConcurrentHashMap with concurrency level 8 
ConcurrentMap<String, Object> map1 = new MapMaker().concurrencyLevel(8).makeMap(); 
Copy the code

Or construct a Map with various references as keys and values:

//ConcurrentMap with soft reference key and weak reference value 
ConcurrentMap<String, Object> map2 = new MapMaker().softKeys().weakValues().makeMap(); 
Copy the code

Or construct a Map that automatically removes time-expired items:

//Automatically removed entries from map after 30 seconds since they are created 
ConcurrentMap<String, Object> map3 = new MapMaker() 
.expireAfterWrite(30, TimeUnit.SECONDS)
.makeMap();
Copy the code

Or construct a Map with a maximum limit:

//Map size grows close to the 100, the map will evict 
//entries that are less likely to be used again 
ConcurrentMap<String, Object> map4 = new MapMaker() 
.maximumSize(100)
.makeMap();
Copy the code

Or provide the ability to automatically add get items to a Map when the Map does not contain them. This feature is useful when a Map is used as a cache:

//Create an Object to the map, when get() is missing in map 
ConcurrentMap<String, Object> map5 = new MapMaker().makeComputingMap( 
 new Function<String, Object>() { 
 public Object apply(String key) { 
 	return createObject(key); 
}});
Copy the code

While these are not the most powerful features, the best part is that MapMaker can provide maps with all of these features:

//Put all features together! 
ConcurrentMap<String, Object> mapAll = new MapMaker() 
.concurrencyLevel(8) 
.softKeys() 
.weakValues() 
.expireAfterWrite(30, TimeUnit.SECONDS) 
.maximumSize(100) 
.makeComputingMap( 
 new Function<String, Object>() { 
 public Object apply(String key) { 
 return createObject(key); 
 }});
Copy the code
Ordering class: this can be done without Ordering

To sort or Max or min Collections, the java.util.Collections class is the first choice, but the key is to provide an implementation of the Comparator interface. Let’s say we have a List to sort, and Foo has two sort keys int a, int b, and int c:

Collections.sort(list, new Comparator<Foo>(){ 
@Override 
public int compare(Foo f1, Foo f2) { 
 	intResultA = f1.a -- f2.a;intResultB = f1.b -- f2.b;return resultA == 0 ? (resultB == 0 ? f1.c – f2.c : resultB) : resultA;
}});
Copy the code

This looks a little bit dizzy, and it’s not much better if you use if-else. See what ComparisonChain can do:

Collections.sort(list, new Comparator<Foo>(){ 
@Override 
return ComparisonChain.start() 
 .compare(f1.a, f2.a) 
 .compare(f1.b, f2.b) 
 .compare(f1.c, f2.c).result();
 }});
Copy the code

If a custom Comparator is used for sorting keywords, the compare method also has an overloaded version that accepts the Comparator. If Foo already has a Comparator for each sort key, using the ComparisonChain we can:

Collections.sort(list, new Comparator<Foo>(){ 
@Override 
return ComparisonChain.start() 
 .compare(f1.a, f2.a, comparatorA) 
 .compare(f1.b, f2.b, comparatorB) 
 .compare(f1.c, f2.c, comparatorC).result(); 
 }});
Copy the code

The Ordring class also provides a method to combine the Comparator objects. And Ordring implements the Comparator interface itself, so it can be used directly as a Comparator:

Ordering<Foo> ordering = Ordering.compound(Arrays.asList(comparatorA, comparatorB, comparatorc)); 
Collections.sort(list, ordering);
Copy the code
Stream-filter

The collections2.filter () method is used to filter the unqualified elements in the collection. For example, filter a List of elements less than 10:

Collection<Integer> filterCollection = 
 Collections2.filter(list, new Predicate<Integer>(){ 
@Override 
public boolean apply(Integer input) { 
 return input >= 10; 
}});
Copy the code
  • Of course, you could write your own loop to do this, but that doesn’t guarantee that elements less than 10 won’t be put into the collection later.

  • The power of filters is that the returned filterCollection still has the ability to reject elements less than 10. Calling filterCollection.add(9) will get you an IllegalArgumentException.


Converter (Stream – map)

The collections2.transform () method is used to transform the elements in the collection. For example, to generate a new Collection, convert all elements of a Set to a formatted String:

Collection<String> formatCollection = 
 Collections2.transform(set, new Function<Integer, String>(){ 
@Override 
public String apply(Integer input) { 
 return new DecimalFormat("# # # #,").format(input); }});Copy the code

conclusion

This has introduced some of the basic features of Guava Collections. You can download the JAR package and other documentation from the Guava-Libraries website. If you use Maven to manage your project dependencies, the Maven central library also provides its version of dependencies. Finally, I hope Guava Collections made your programming job easier and more fun.

use

Jar packages published by the open source project can be found on its official website (code.google.com/p/guava-lib…

Jar and its dependencies guava-r09-GWt. jar, Javadoc, source code, readme, etc. To use it, simply put guava-r09.jar and its dependencies guava-r09-GWt.jar into your CLASSPATH.

If you use Maven as a build tool you can add the following to pom.xml:

<dependency> 
<groupId>com.google.guava</groupId> 
<artifactId>guava</artifactId> 
<version>xxx</version> 
</dependency> 
Copy the code