Site icon JVM Advent

Hidden Treasures of Eclipse Collections 2023 Edition

Eclipse Collections is an open source Java Collections framework. In this blog I am going to demonstrate four lesser known features of the framework. I have published similar blogs in Java Advent Calendars of 2018, 2019, 2020, 2021, and 2022. Please refer to the resources at the end of the blog for more information about the framework.

  1. HashingStrategy: If you want to define a hashing strategy to have a custom hashCode() and equals() without overriding the default hashCode() and equals() then use HashingStrategy. This is particularly useful in conjunction with UnifiedSetWithHashingStrategy, UnifiedMapWithHashingStrategy, and HashBagWithHashingStrategy. The code examples HashingStrategy and Collections with HashingStrategy are presented together
  2. Collections with HashingStrategy: Eclipse Collections offers Set, Map, and Bag wherein the uniqueness is determined by a custom hashCode() and equals() . This is particularly useful when we cannot modify the default hashCode() and equals(). This is generally useful during data processing before inserting in the database. Hashing Strategies can be used to ensure uniqueness based on a primary key. This is especially useful while using Java Records.
    // Domain
    public record Person(String firstName, String lastName) {
    }
    
    Person person1 = new Person("Alex", "Smith");
    Person person2 = new Person("John", "Smith");
    Person person3 = new Person("John", "Brown");
    List<Person> people = Lists.mutable.of(person1, person2, person3);
    
    // Uniqueness is defined by Last Name
    HashingStrategy<Person> LAST_NAME_HASHING_STRATEGY = 
            HashingStrategies.fromFunction(Person::lastName);
    @Test
    public void unifiedSetWithHashingStrategy() {
    
        MutableSet<Person> hashingStrategySet =
                UnifiedSetWithHashingStrategy.newSet(
                        LAST_NAME_HASHING_STRATEGY,
                        people);
    
        Assertions.assertEquals(
                Sets.mutable.with(person1, person3),
                hashingStrategySet,
                "Uniqueness defined by only Last Name");
    }
    
    
    
    @Test
    public void unifiedMapWithHashingStrategy() {
    
        MutableMap<Person, Integer> hashingStrategyMap =
                UnifiedMapWithHashingStrategy.newMapWith(LAST_NAME_HASHING_STRATEGY);
        hashingStrategyMap.put(person1, 1);
        // The key is considered same due to same last name.
        // Hence, by Map symantics, the new value will be stored
        hashingStrategyMap.put(person2, 2);
        hashingStrategyMap.put(person3, 3);
    
        Assertions.assertEquals(
                Maps.mutable.with(person1, 2, person3, 3),
                hashingStrategyMap,
                "Uniqueness defined by only Last Name");
    }
    @Test
    public void hashBagWithHashingStrategy() {
    
        MutableBag<Person> hashingStrategyBag =
                HashBagWithHashingStrategy.newBag(
                        LAST_NAME_HASHING_STRATEGY,
                        people);
    
        Assertions.assertEquals(
                Bags.mutable.with(person1, person1, person3),
                hashingStrategyBag,
                "Uniqueness defined by only Last Name, hence, person1 comes up twice");
    }
  3. detect: is used to find the first instance of an element that satisfies the Predicate. In case no element satisfies the Predicate then a null is returned. This method is similar to findFirst() in JDK Collections except that a null is returned when no element is found.
    @Test
    public void detect() {
        var list = Lists.mutable.with(1, 2, 3);
    
        Assertions.assertEquals(
                2,
                list.detect(each -> each % 2 == 0));
        Assertions.assertNull(
                list.detect(each -> each % 4 == 0));
    }
  4. detectOptional: This is a correlated method to detect wherein instead of returning an element that satisfies the Predicate an Optional is returned. In case no element satisfies the Predicate then an empty Optional is returned. This method is equivalent to findFirst() in JDK Collections.
    @Test
    public void detectOptional() {
        var list = Lists.mutable.with(1, 2, 3);
    
        Assertions.assertEquals(
                Optional.of(2),
                list.detectOptional(each -> each % 2 == 0));
        Assertions.assertEquals(
                list.stream()
                        .filter(each -> each % 2 == 0)
                        .findFirst(),
                list.detectOptional(each -> each % 2 == 0));
    
        Assertions.assertEquals(
                Optional.empty(),
                list.detectOptional(each -> each % 4 == 0));
        Assertions.assertEquals(
                list.stream()
                        .filter(each -> each % 4 == 0)
                        .findFirst(),
                list.detectOptional(each -> each % 4 == 0));
    }

Summary

In this blog I explained a few lesser known features of Eclipse Collections namely HashingStrategy, Collections with HashingStrategies, detect, and detectOptional.

I hope you found the post informative. If you have not used Eclipse Collections before, give it a try. There are few resources below. Make sure you show us your support and put a star on our GitHub Repository

Eclipse Collections Resources

Eclipse Collections comes with it’s own implementations of ListSet and Map. It also has additional data structures like MultimapBag and an entire Primitive Collections hierarchy. Each of our collections have a fluent and rich API for commonly required iteration patterns.

Author: Nikhil Nanivadekar

Lead Eclipse Collections: eclipse.org/collections, Java Champion. I enjoy hiking, skiing, reading. All opinions stated by me are my own.

Exit mobile version