After writing a lot of articles about Java collection classes and learning the usage of a lot of collection classes, do you feel that there are still some common requirements that collection classes cannot meet? We need to implement it ourselves using classes in the Java collection, but Google and Apache have built the common wheels for us.

There are two well-known Java-related toolkits,Google Guava and Apache Commons, and today we’ll take a look at some of the other collection classes implemented in Guava, which are basically enhancements to the JDK’s collection classes.

Immutable Collections -> Truly Immutable Collections

In the Java Collections section above, we mentioned that the Collections class provides methods that can return an immutable view of the collection, so let’s try it out.

Let’s create a new list with five elements. Then create an immutable view of it.

        List<Integer> list = new ArrayList<>(Arrays.asList(1.2.3.4.5));
        List<Integer> umList = Collections.unmodifiableList(list);
Copy the code

After the above steps, we get the umList. It is immutable, but the list does not disappear. It is still mutable, and we can change the set of elements in the umList by adding a value to the list.

Because in the Collections. UnmodifiableList, holds a list of references, all on the list of changes will also embodies in umList simultaneously.

And in the above code, there is an intermediate variable list. Since we don’t need it, we create it just to get the immutable set that follows. It’s tedious.

How do you do that with Guava? Something like this:


ImmutableCollection li = ImmutableList.of(1.2.3.4.5);

Copy the code

Doesn’t it feel a lot clearer, and at the same time, this Li is really immutable.

ImmutableList also provides several methods to create a list, such as:

  1. Directly created using the arguments of any element.
  2. usecopyOfCreate from an existing List
  3. Provide Builder mode to make chain calls.

The code above USES the example of ImmutableList, but ImmutableMap, Guava also provides ImmutableSet ImmutableCollection class, can according to the need of data structure called respectively.

MultiMap -> another solution to Map<Strinh,List>

There is often a need to store a List/Set in a Map structure.

[2019-04-01,2019-04-28] [name->[2019-04-01,2019-04-28]

So what if we add a user’s check-in on May 1st? Write code all at once,

    // Simulate existing data structures
    static Map<String, List<String>> userSign = new HashMap<>();
    // Add a new piece of data
    public static void putIt(String name, String date) {
	// The formal logical part
        List<String> dates = userSign.getOrDefault(name, new ArrayList<>());
        if(! dates.contains(date)) { dates.add(date); } userSign.put(name, dates); }Copy the code

As you can see, it’s a bit more cumbersome, and if it weren’t for Map’s getOrDefault() method, the code would be a few more lines, as it would have to be split into existing and non-existing ones.

Guava provides a data structure to store this case of multiple values for one key, called a MultiMap.

Although his name comes with map, a look at the source code shows that his class life does not inherit the Map interface.

To implement the above method using MultiMap, just look like this:


        ArrayListMultimap<String, String> userSign = ArrayListMultimap.create();
        userSign.put("huyan"."2019-05-01");
        userSign.put("huyan"."2019-05-02");

        List<String> huyanSign = userSign.get("huyan");

Copy the code

If you want to consume it, use get to get an Arratlist and iterate through it.

Map<String,List> is used to implement Guava. This is where the definition is:

Map

is defined. Collection is defined to implement other centralized data structures.
,collection

Such as:

  • HashMultimapThe value of is placed in set
  • LinkedListMultimapIs placed in the LinkedList.

And so on.

Multiset -> a counter named set

To be honest, it works pretty well, but why set… You can’t put duplicate elements in a set, but a Multiset counts duplicate elements.

The usage is as follows:


        Multiset<String> s = HashMultiset.create();
        s.add("pf");
        s.add("pf");
        s.add("pf");
        s.add("hh");
	// i =3
        int i = s.count("pf");

Copy the code

This works the same way as the counter I wrote the other day, the counter portal.

The internal implementation uses a HashMap to hold a mapping of key->count.

BiMap -> value also cannot be a duplicate bidirectional Map

This class actually implements the JDK’s Map interface, and must be used to ensure that neither key nor value has duplicate values. Because it supports fetching keys by value, the key and value of the HashMap are swapped.

        BiMap<String, String> m = HashBiMap.create();

        m.put("pf"."111");

        String value = m.get("pf");
        String key = m.inverse().get("111");
Copy the code

This class is suitable for both key and value, and it is common to get a key based on value.

Table -> Map<String,Map<String,Object>

Map

> is possible, but it is too difficult to understand and code.
,map

Guava provides a data structure called Table that can be implemented elegantly.

Use as follows:

        Table<Integer, Integer, String> tt = HashBasedTable.create();
        tt.put(1.2."huyan");

        String name = tt.get(1.2);
        Map<Integer, String> row = tt.row(1);
        Map<Integer, String> colum = tt.column(1);
        Set<Table.Cell<Integer, Integer, String>> ha = tt.cellSet();

Copy the code

The method of initialization is no different from the above structures, which are initialized using static factory methods. The GET and PUT methods store and uniquely index a single piece of data based on two indexes.

In addition, you can get a Map structure for a row or a column, you can get a set for all the cells. Great convenience for handling tabular data.

, of course, have a look at the source code will find, in fact, the Table is to use two map at the bottom of the nested, but the Java language, pay attention to is a wrapper, although we can achieve our, but we should do is to learn the good implementation method, read, understood and can be applied in other scenarios similar ideas, since not every time I’ve written two maps. After all, ready-made wheels should be used in appropriate situations to deepen understanding.

ComparisonChain -> a ComparisonChain comparison method

Our code is usually ugly in scenarios where multiple fields are sorted and compared, such as the following class:

    private static class Student {
        int id;
        String name;
        int age;
    }

Copy the code

There is no way to compare or sort it now, because there is no defined comparison strategy for it. Suppose our strategy is:

Id is compared first, ID equality is compared to name, and name equality is compared to age, which is a very common multi-field comparison strategy. So let’s add the Comparable implementation to the Student class.

	// For brevity, there is no external class code, just the overriding comparTo method.
        @Override
        public int compareTo(Object o) {
            Student s = (Student) o;
            int idResult = s.id - this.id;
            int nameResult = s.name.compareTo(this.name);
            int ageResult = s.age - this.age;

            returnidResult ! =0? idResult : nameResult ! =0 ? nameResult : ageResult;
        }

Copy the code

The last one? 😕 : Is not looking at the eye pain, of course you can choose triple if-else, I feel not good to where to go.

Instead, we can use the ComparisonChain, which looks like a ComparisonChain, and it’s very appropriate for our scenario. Rewrite as follows:

 @Override
        public int compareTo(Object o) {
            Student s = (Student) o;
            return ComparisonChain.start().compare(s.id, this.id).compare(s.name, this.name).compare(s.age, this.age).
                    result();
        }
Copy the code

This code readability can be said to be very large, very clear semantics, can be very clear to understand the process of starting, first compare, then compare, return the result.

Ordering -> A combination of comparators

ComparisonChain resolves the need for multiple fields to be sorted with Comparable. There are many methods in the JDK that require an external comparator.

Orderings provides a way to use multiple comparators. It implements the Comparator interface and can integrate multiple comparators.

Ordering<Student> studentOrdering = Ordering.compound(Arrays.asList((o1, o2) -> {
            return ComparisonChain.start().result();
        }, (o1, o2) -> 0, (o1, o2) -> 0));
Collections.sort(students, studentOrdering);
Copy the code

In the code above, we integrate multiple comparators using Ordering, then pass itself into the Collections sort method, and use it to sort the list.











ChangeLog





All the above are personal thoughts, if there is any mistake welcome to comment.

Welcome to reprint, please sign and keep the original link.

Contact email: [email protected]

For more study notes, see my personal blog ——>HuYan ten