Recently, when I was looking at one of my classmates’ codes, I found that Google’s open-source Guava core library was extensively used in the code, which made the code much simpler and clearer. Therefore, I learned to share the most practical functions in Guava.

Guava project is an open source Java core library of Google. It mainly contains some functions frequently used in Java development, such as data verification, immutable collection, count collection, collection enhancement operation, I/O, cache, string operation, etc. And Guava is widely used in Java projects within Google, as well as by other companies, and has even directly introduced the excellent class libraries from Guava in the new JDK, so there is no doubt about its quality.

Use mode directly mavan dependent introduction.

<! -- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.0 the jre</version>
</dependency>
Copy the code

Data validation

Data verification is very simple, one is non-null judgment, the other is expected value judgment. I’m sure every Java developer is familiar with NullPointException from the beginning. If (xx == null) can be easily solved. Expected value judgment is similar, check whether the data value is the result you want.

Even with this simple operation, do we often make mistakes? And the code is always written to determine the line of exception thrown, which is elegant in every way. Well, let’s try Guava for the first time.

Judge not empty

String param = "Unread code";
String name = Preconditions.checkNotNull(param);
System.out.println(name); // Unread code
String param2 = null;
String name2 = Preconditions.checkNotNull(param2); // NullPointerException
System.out.println(name2);
Copy the code

Guava is introduced can be used directly after Preconditions. CheckNotNull for judging is not empty, good to think that there are two, one is the semantic clear code elegant; Second, you can also customize the error message, so that if the parameter is empty, the error message is clear, you can directly locate the specific parameter.

String param2 = null;
String name2 = Preconditions.checkNotNull(param2,"param2 is null");
// java.lang.NullPointerException: param2 is null
Copy the code

Expected value judgment

Similar to the non-null judgment, you can compare the current value with the expected value. If the value is not equal, you can customize the error message thrown.

String param = "www.wdbyte.com2";
String wdbyte = "www.wdbyte.com";
Preconditions.checkArgument(wdbyte.equals(param), "[%s] 404 NOT FOUND", param);
// java.lang.IllegalArgumentException: [www.wdbyte.com2] 404 NOT FOUND
Copy the code

Whether cross-border

The Preconditions class can also be used to check if element fetching in arrays and collections is out of bounds.

// Create ArrayList quickly in Guava
List<String> list = Lists.newArrayList("a"."b"."c"."d");
// Start verification
int index = Preconditions.checkElementIndex(5, list.size());
// java.lang.IndexOutOfBoundsException: index (5) must be less than size (4)
Copy the code

The way to quickly create lists in code is also provided by Guava, more on the super-multiple poses for collection creation in Guava later.

Immutable set

Creating immutable collections is one of my personal favorites of Guava, because it’s so practical to create a collection that can’t be deleted, modified, or added to. You don’t have to worry about any problems with such a collection. In general, it has the following advantages:

  1. Thread-safe, because you can’t modify any elements, can be multithreaded at will with no concurrency problems.
  2. Can be worry-free to provide third party use, anyway can not modify.
  3. Reduce memory footprint, since it cannot be changed, so internal implementations can save the most memory footprint.
  4. Can be used as a set of constants.

Create a way

All that said, how do you use it? Now pull up the code.

// Create method 1: of
ImmutableSet<String> immutableSet = ImmutableSet.of("a"."b"."c");
immutableSet.forEach(System.out::println);
// a
// b
// c

// Create method 2: builder
ImmutableSet<String> immutableSet2 = ImmutableSet.<String>builder()
    .add("hello")
    .add(new String("Unread code"))
    .build();
immutableSet2.forEach(System.out::println);
// hello
// Unread code

// Create method 3: copy from another collection
ArrayList<String> arrayList = new ArrayList();
arrayList.add("www.wdbyte.com");
arrayList.add("https");
ImmutableSet<String> immutableSet3 = ImmutableSet.copyOf(arrayList);
immutableSet3.forEach(System.out::println);
// www.wdbyte.com
// https
Copy the code

Can print normal traversal results, but if to increase, deletion UnsupportedOperationException directly.

The JDK also provides an immutable collection, which can be created as follows.

ArrayList<String> arrayList = new ArrayList();
arrayList.add("www.wdbyte.com");
arrayList.add("https");
// JDK Collections creates immutable lists
List<String> list = Collections.unmodifiableList(arrayList);
list.forEach(System.out::println);// www.wdbyte.com https
list.add("Unread code"); // java.lang.UnsupportedOperationException
Copy the code

Matters needing attention

  1. Null values are rejected in immutable collections created with Guava, because in internal Google surveys, null values are not required 95% of the time.

  2. Once created using an immutable collection provided by the JDK, elements added to the original collection are reflected in the immutable collection, while Guava’s immutable collection does not have this problem.

    List<String> arrayList = new ArrayList<>();
    arrayList.add("a");
    arrayList.add("b");
    List<String> jdkList = Collections.unmodifiableList(arrayList);
    ImmutableList<String> immutableList = ImmutableList.copyOf(arrayList);
    arrayList.add("ccc");
    jdkList.forEach(System.out::println);// result: a b ccc
    System.out.println("-- -- -- -- -- -- --");
    immutableList.forEach(System.out::println);// result: a b
    Copy the code
  3. If the elements of an immutable collection are reference objects, the attributes of reference objects can be changed.

Other immutable sets

Immutable sets In addition to the set demonstrated above, there are many immutable sets. Here is how immutable sets correspond to other sets in Guava.

Variable set interface JDK or Guava Immutable version
Collection JDK ImmutableCollection
List JDK ImmutableList
Set JDK ImmutableSet
SortedSet/NavigableSet JDK ImmutableSortedSet
Map JDK ImmutableMap
SortedMap JDK ImmutableSortedMap
Multiset Guava ImmutableMultiset
SortedMultiset Guava ImmutableSortedMultiset
Multimap Guava ImmutableMultimap
ListMultimap Guava ImmutableListMultimap
SetMultimap Guava ImmutableSetMultimap
BiMap Guava ImmutableBiMap
ClassToInstanceMap Guava ImmutableClassToInstanceMap
Table Guava ImmutableTable

Set operation factory

In fact, there is only one creation method here, but why is it presented separately? It’s gonna make you scream. Although the JDK already provides a large number of collection-related operations that are very easy to use, Guava has added some very useful methods that are guaranteed to keep you hooked the first time you use them.

Create a collection.

// Create an ArrayList collection
List<String> list1 = Lists.newArrayList();
// Create an ArrayList collection with three data items
List<String> list2 = Lists.newArrayList("a"."b"."c");
// Create a collection of ArrayLists initialized to 10
List<String> list3 = Lists.newArrayListWithCapacity(10);

LinkedList<String> linkedList1 = Lists.newLinkedList();
CopyOnWriteArrayList<String> cowArrayList = Lists.newCopyOnWriteArrayList();

HashMap<Object, Object> hashMap = Maps.newHashMap();
ConcurrentMap<Object, Object> concurrentMap = Maps.newConcurrentMap();
TreeMap<Comparable, Object> treeMap = Maps.newTreeMap();

HashSet<Object> hashSet = Sets.newHashSet();
HashSet<String> newHashSet = Sets.newHashSet("a"."a"."b"."c");
Copy the code

Guava adds factory method creation for each collection, which has been shown above for some collections. Is not very easy to use. And you can just throw in a few elements at creation time, which is awesome, so you don’t have to add them one by one.

Set intersection union difference set

Too simple, just look at the code and the output.

Set<String> newHashSet1 = Sets.newHashSet("a"."a"."b"."c");
Set<String> newHashSet2 = Sets.newHashSet("b"."b"."c"."d");

/ / intersection
SetView<String> intersectionSet = Sets.intersection(newHashSet1, newHashSet2);
System.out.println(intersectionSet); // [b, c]

/ / and set
SetView<String> unionSet = Sets.union(newHashSet1, newHashSet2);
System.out.println(unionSet); // [a, b, c, d]

NewHashSet1 does not exist in newHashSet2
SetView<String> setView = Sets.difference(newHashSet1, newHashSet2);
System.out.println(setView); // [a]
Copy the code

There are sets of quantities

And this is really useful, because we often need to design collections that we can count, or values that are maps of lists, and if you don’t understand, look at this code, and see if you’ve ever done this one night.

  1. Count the number of occurrences of the same element (I’ve written the following code as succinctly as possible).

    JDK native:

    Java counts the number of occurrences of the same element.
    List<String> words = Lists.newArrayList("a"."b"."c"."d"."a"."c");
    Map<String, Integer> countMap = new HashMap<String, Integer>();
    for (String word : words) {
        Integer count = countMap.get(word);
        count = (count == null)?1 : ++count;
        countMap.put(word, count);
    }
    countMap.forEach((k, v) -> System.out.println(k + ":" + v));
    /** * result: * a:2 * b:1 * c:2 * d:1 */
    Copy the code

    Despite the best efforts to optimize the code, the amount of code is still quite large, so what’s different in Guava? The main use of the HashMultiset class in Guava. See below.

    ArrayList<String> arrayList = Lists.newArrayList("a"."b"."c"."d"."a"."c");
    HashMultiset<String> multiset = HashMultiset.create(arrayList);
    multiset.elementSet().forEach(s -> System.out.println(s + ":" + multiset.count(s)));
    /** * result: * a:2 * b:1 * c:2 * d:1 */
    Copy the code

    Yes, you can just add elements to it, regardless of whether they are duplicated or not, and use the count method to count the number of duplicated elements. Comfortable to look at and elegantly written, HashMultiset is a Collection class implemented in Guava that makes it easy to count elements.

  2. One-to-many, value is a Map set of lists.

    Imagine a scenario where you need to sort a lot of animals by species, and I’m sure you’ll end up writing code like this.

    JDK native:

    HashMap<String, Set<String>> animalMap = new HashMap<>();
    HashSet<String> dogSet = new HashSet<>();
    dogSet.add("Prosperous wealth.");
    dogSet.add("Rhubarb");
    animalMap.put("Dog", dogSet);
    HashSet<String> catSet = new HashSet<>();
    catSet.add("Garfield");
    catSet.add("Tom");
    animalMap.put("Cat", catSet);
    System.out.println(animalMap.get("Cat")); // [Garfield, Tom]
    Copy the code

    The last line of the cat query yielded “Garfield” and “Tom” for cats. This code is just too annoying to do. What if you use Guava?

    // use guava
    HashMultimap<String, String> multimap = HashMultimap.create();
    multimap.put("Dog"."Rhubarb");
    multimap.put("Dog"."Prosperous wealth.");
    multimap.put("Cat"."Garfield");
    multimap.put("Cat"."Tom");
    System.out.println(multimap.get("Cat")); // [Garfield, Tom]
    Copy the code

    HashMultimap can throw in duplicate keys, and when it finally gets all the values, you can see that the output is the same as it was written in the JDK, but the code is very clean.

String manipulation

As the longest used data type in development, enhancements to string manipulation can make development more efficient.

Characters joining together

The string concatenation method is already built into JDK 8, but it is simple concatenation with no additional operations, such as filtering out null elements and removing surrounding whitespace. Let’s take a look at some of the ways string concatenation works in JDK 8.

// JDK method 1
ArrayList<String> list = Lists.newArrayList("a"."b"."c".null);
String join = String.join(",", list);
System.out.println(join); // a,b,c,null
// JDK mode 2
String result = list.stream().collect(Collectors.joining(","));
System.out.println(result); // a,b,c,null
// JDK mode 3
StringJoiner stringJoiner = new StringJoiner(",");
list.forEach(stringJoiner::add);
System.out.println(stringJoiner.toString()); // a,b,c,null
Copy the code

You can see that null values are also concatenated into strings, which is sometimes not what we want, so what’s different with Guava?

ArrayList<String> list = Lists.newArrayList("a"."b"."c".null);
String join = Joiner.on(",").skipNulls().join(list);
System.out.println(join); // a,b,c

String join1 = Joiner.on(",").useForNull("Null").join("Prosperous wealth."."Tom"."Jerry".null);
System.out.println(join1); // Rich, Tom, Jerry, null
Copy the code

You can use skipNulls() to skip null values, and useFornull(String) to customize the display of text for null values.

String splitting

JDK is built-in String, I think you must have been used, that is a String of the split method, but there is a problem with this approach, is that if the last element is empty, so will be discarded, the strange thing is the first element is empty but not discard, this is very confused, through an example demonstrates the problem below.

String str = ",a,,b,";
String[] splitArr = str.split(",");
Arrays.stream(splitArr).forEach(System.out::println);
System.out.println("------");
/**
 *
 * a
 * 
 * b
 * ------
 */
Copy the code

You can also test for yourself that the last element is not empty, it just disappears.

How does it work with Guava? Guava provides the Splitter class, and has a series of operations to intuitively control the segmentation logic.

String str = ",a ,,b ,";
Iterable<String> split = Splitter.on(",")
    .omitEmptyStrings() // Ignore null values
    .trimResults() // Filter whitespace in the result
    .split(str);
split.forEach(System.out::println);
/** * a * b */
Copy the code

The cache

We may need to use small caches during development to increase access speed. At this point, introducing professional caching middleware may feel wasteful. Now, Guava provides simple caching classes that automatically expire elements that have been added based on expected capacity, expiration time, and so on. Even then, we need to estimate the amount of memory we are likely to use so that we don’t overdo it.

Now let’s see how caching works in Guava.

@Test
public void testCache(a) throws ExecutionException, InterruptedException {

    CacheLoader cacheLoader = new CacheLoader<String, Animal>() {
        // If no element is found, this is called
        @Override
        public Animal load(String s) {
            return null; }}; LoadingCache<String, Animal> loadingCache = CacheBuilder.newBuilder() .maximumSize(1000) / / capacity
        .expireAfterWrite(3, TimeUnit.SECONDS) // Expiration time
        .removalListener(new MyRemovalListener()) // Invalid listener
        .build(cacheLoader); //
    loadingCache.put("Dog".new Animal("Prosperous wealth.".1));
    loadingCache.put("Cat".new Animal("Tom".3));
    loadingCache.put("The Wolf".new Animal("Big Big Wolf".4));

    loadingCache.invalidate("Cat"); // Manual failure

    Animal animal = loadingCache.get("The Wolf");
    System.out.println(animal);
    Thread.sleep(4 * 1000);
    // The Wolf has automatically passed, the value is null error
    System.out.println(loadingCache.get("The Wolf"));
    /** * key= EXPLICIT; /** * key= EXPLICIT; /** * key= EXPLICIT; /** * key= EXPLICIT; Age =1},reason=EXPIRED * key= Wolf,value=Animal{name=' Wolf ', age=4},reason=EXPIRED * * com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key Wolf. */
}

/** * cache removal listener */
class MyRemovalListener implements RemovalListener<String.Animal> {

    @Override
    public void onRemoval(RemovalNotification<String, Animal> notification) {
        String reason = String.format("key=%s,value=%s,reason=%s", notification.getKey(), notification.getValue(), notification.getCause()); System.out.println(reason); }}class Animal {
    private String name;
    private Integer age;

    @Override
    public String toString(a) {
        return "Animal{" +
            "name='" + name + '\' ' +
            ", age=" + age +
            '} ';
    }

    public Animal(String name, Integer age) {
        this.name = name;
        this.age = age; }}Copy the code

In this example, there are CacheLoader, MyRemovalListener, and LoadingCache.

The load method will be called if there is no hit in the cache. I returned null. This will return null for the key if there is no hit.

MyRemovalListener is the listener class that listens when the cache element fails. OnRemoval is automatically called when the cache element fails. Note that this method is synchronous, and if it takes a long time, it will block until processing is complete.

LoadingCache is the main operation object of the cache. The commonly used methods are put and GET.

conclusion

Guava is Google’s open source Java development core library. I think it is very practical. After the introduction, it can not only quickly realize some commonly used functions in development, but also make the code more elegant and concise. I think this applies to every Java project. Other features of Guava you can discover for yourself. Its Github address is github.com/google/guav… .

reference

  1. Github.com/google/guav…

To subscribe to

The article is available at Github.com/niumoo/Java… Welcome Star and advice. There are also some articles such as pilot of big factory surface and core knowledge Java programmers need to master. I have also sorted out a lot of my words. Welcome Star and Perfection, and I hope we can become excellent together.

The article continues to update every week, if there is help, you can click a “like” or “share”, all is support, I like!

To follow updated articles and shared dry goods in real time, you can follow the unread code public account (qr code below) or my website.