DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • What Is a Jagged Array in Java With Examples?
  • Reversing an Array: An Exploration of Array Manipulation
  • Effective Java Collection Framework: Best Practices and Tips
  • Unlocking the Potential of Binary Search Trees with C# Programming

Trending

  • Is Agile Right for Every Project? When To Use It and When To Avoid It
  • Developers Beware: Slopsquatting and Vibe Coding Can Increase Risk of AI-Powered Attacks
  • Memory Leak Due to Time-Taking finalize() Method
  • Unlocking AI Coding Assistants: Generate Unit Tests
  1. DZone
  2. Data Engineering
  3. Data
  4. The Bag Data Structure From Eclipse Collections

The Bag Data Structure From Eclipse Collections

Bags are data structures that permit holding duplicates in any order. This is similar to a physical bag, where you could also put any elements and take them out randomly.

By 
Yuri Mednikov user avatar
Yuri Mednikov
·
Jul. 16, 21 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
6.4K Views

Join the DZone community and get the full member experience.

Join For Free
In computer science, a bag is defined as an abstract data structure, that allows keeping duplicate elements in any order. This is similar to a physical bag, where you could also put any elements and take them out randomly. So, bags are different from lists (because lists care about a particular position of an element) and from sets (because sets do not allow duplicates). The bag is a good choice when you just need to collect items and do some processing using iterations. Java does not offer its "vanilla" implementation of the bag, however, you could find it in popular collections libraries. In this post, we will review the Bag from Eclipse Collections, which supplies both mutable and immutable versions.

Create Bags

Before we will proceed with various Bag methods, let observe how to initialize a new Bag instance within the Eclipse Collections framework. Likewise to other types of collections, there are presented both mutable (modifiable) and immutable (non-modifiable) versions. In general, we can use the Bags class, which allows utilizing static factory methods to obtain bags:

  • Bags.immutable.* calls ImmutableBagFactory to create immutable bags.
  • Bags.mutable.* calls MutableBagFactory to create mutable bags.

Both types use the same approaches, that can be separated into the following three categories:

  • *.empty() = create an empty bag (the bag that does not contain any elements).
  • *.of()/*.with() = allows creating a bag that contains a single element or many elements (using varargs in the latter case).
  • *.ofAll()/*.withAll() = allows creating a bag with elements of the other Iterable implementation (basically any collection).

There is important to note, that generally all other Eclipse Collections data structures are created in a similar way. Now, as we defined how to obtain a new instance, let have a practical example. In the code snippet below we initialize a new ImmutableBag that keeps 4 elements, defined during its creation:

Java
 
@Test
void createBagTest(){
    ImmutableBag<Employee> employees = Bags.immutable.of(
            new Employee(1, "Andrea Novakova", Department.MANAGEMENT),
            new Employee(2, "Borislav Vojtek", Department.IT),
            new Employee(3, "Denisa Zizkova", Department.DELIVERY),
            new Employee(4, "Marek Ruzicka", Department.HR)
    );

    Assertions.assertThat(employees.size()).isEqualTo(4);
}


That gives us the new Bag collection. As I mentioned already, mutable versions are created in a same manner, however they allow to modify their items. On the other hand, immutable data structures do not allow to modify elements and create new instances, when elements are inserted or removed, in order to not affect initial data. In next sections, we will observe common operations with bags, using Eclipse Collections.

Detect Elements

From the theoretical point of view, bags do not track elements in any way, like, for instance, lists, that use an index to access a particular item. But we may need to search for elements in the bag and to verify that the element is presented. For that task, we could rely on detection methods. The detection is what is called a short circuit operation, because an execution is terminated, once the logical condition is satisfied. This condition is defined in a form of a predicate (lambda expression which represents a single argument function that returns a boolean value). There are several detection methods available for bags. Let start with the general detect() one:

Java
 
ImmutableBag<Employee> employees = Bags.immutable.of(
        new Employee(1, "Andrea Novakova", Department.MANAGEMENT),
        new Employee(2, "Borislav Vojtek", Department.IT),
        new Employee(3, "Denisa Zizkova", Department.DELIVERY),
        new Employee(4, "Marek Ruzicka", Department.HR)
);

// detect()
Employee andrea = employees.detect(e -> e.getName().equalsIgnoreCase("Andrea Novakova"));
Assertions.assertThat(andrea).isNotNull();
Assertions.assertThat(andrea.getEmployeeId()).isEqualTo(1);
Assertions.assertThat(andrea.getDepartment()).isEqualByComparingTo(Department.MANAGEMENT);


In this code snippet, we look for an employee with a specific name. For this, we provide a predicate function, that evaluates an element to have the name "Andrea Novakova", and once the element is found, the execution is terminated and the element is returned. If the element within the defined query is not found, the method simply returns a null value. So, we need to do what is called “null checking”, which is not really a good idea. It is better to get an optional result, that can be performed with the detectOptional() method. Take a look at the code snippet below:

Java
 
Optional<Employee> petr = employees.detectOptional(e -> e.getName().equalsIgnoreCase("Petr Vodicka"));
Assertions.assertThat(petr).isEmpty();


Lastly, you may want to return a default value, if the element is not found. That can be done using the detectIfNone() method:

Java
 
Employee jana = employees.detectIfNone(e -> e.getName().equalsIgnoreCase("Jana Dvorakova"), 
                () -> new Employee(7, "Jana Novakova", Department.IT));

Assertions.assertThat(jana).isNotNull();
Assertions.assertThat(jana.getEmployeeId()).isEqualTo(7);
Assertions.assertThat(jana.getDepartment()).isEqualByComparingTo(Department.IT);


To sum up this section, we can say, that detection in Eclipse Collections is what is usually referred to as find methods. These functions allow to look for a specific element in the bag, and optionally to return a default value. If you need to look for several elements, you need to review selections and rejections.

Select and Reject Elements

These two groups of methods are placed in a single section because basically, they work in a similar way. They both look for elements into an existing collection, that are evaluated against a logical condition. The difference between selection and rejection is that the select operation returns a collection, that contain elements that do satisfy the predicate. From the opposite side, rejections do collect elements that do not satisfy the predicate.

Basic versions of both operations take a predicate, that is used to evaluate elements. Take a look at the usage of the select() method:

Java
 
ImmutableBag<Employee> employees = Bags.immutable.of(
        new Employee(1, "Andrea Novakova", Department.MANAGEMENT),
        new Employee(2, "Borislav Vojtek", Department.IT),
        new Employee(3, "Denisa Zizkova", Department.IT),
        new Employee(4, "Marek Ruzicka", Department.HR)
);

// select with predicate
ImmutableBag<Employee> itEmployees = employees.select(e -> e.getDepartment() == Department.IT);
Assertions.assertThat(itEmployees.size()).isEqualTo(2);


The rejection operation works similar to the selection, but it returns a new collection, that does not contain elements, that are valid for the predicate:

Java
 
@Test
void rejectTest(){
    ImmutableBag<Integer> numbers = Bags.immutable.of(1,2,3,4,5,6,7,8,9,10);
    ImmutableBag<Integer> odd = numbers.reject(e -> e % 2 == 0);
    Assertions.assertThat(odd.toList()).contains(1,3,5,7,9);
}


Besides, there are several built-in methods that can be used to select elements from the original bag that do not have duplicates or that do have duplicates:

  • selectUnique() = this method returns a set (collection of unique elements) containing all elements of the bag that are presented only once.
  • selectDuplicates() = this method returns a bag containing all elements of the bag that are presented more than once.

Take a look at the following code snippet below:

Java
 
ImmutableBag<Integer> numbers = Bags.immutable.of(1,2,3,3,5,1,10,6,9,15);

// select unique (only that do not have duplicates!)
ImmutableSet<Integer> unique = numbers.selectUnique();
Assertions.assertThat(unique.castToSet())
        .containsExactlyInAnyOrder(2,5,6,9,10,15)
        .doesNotContain(1,3); // 1 and 3 have duplicates!

// select duplicates
ImmutableBag<Integer> duplicates = numbers.selectDuplicates();
Assertions.assertThat(duplicates.toList()).contains(1,3);


Use Iterators

The iterator pattern is one of the approaches to access elements of a collection, alongside streams. From a technical point of view, the iterator traverses elements in sequential and predictable order. In Java, the behavior of iterators is defined in the java.util.Iterator interface, which is a member of the Java Collections Framework.

Iterators are similar to enumerators, but there are differences between these concepts too. The enumerator provides indirect and iterative access to each element of a data structure exactly once. On the other side, iterators do the same task, but the traversal order is predictable. With this abstraction, a caller can work with collection elements, without direct access to them. Also, iterators allow deleting values from a collection during the iteration.

Eclipse Collections permits to access iterators using the iterator() method, that is inherited from the Iterable interface. Take a look at the example code below:

Java
 
@Test
void iteratorTest(){
    ImmutableBag<Integer> numbers = Bags.immutable.of(1,2,3,4,5);
    Iterator<Integer> iterator = numbers.iterator();

    int sum = 0;
    while (iterator.hasNext()){
        int val = iterator.next();
        sum += val;
    }

    Assertions.assertThat(sum).isEqualTo(15);
}


Source Code

You can access example code snippets for this post here. Feel free to explore it!

Summary

Bags are data structures that permit holding duplicates in any order. The standard Java Collections Framework does not supply their implementations, but you can utilize the one from Eclipse Collections. In this post, we reviewed the essential functions of this class. If you have questions regarding this post or suggestions, please feel free to contact me.

Bag Element Eclipse Data (computing) Data structure Java (programming language)

Published at DZone with permission of Yuri Mednikov. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • What Is a Jagged Array in Java With Examples?
  • Reversing an Array: An Exploration of Array Manipulation
  • Effective Java Collection Framework: Best Practices and Tips
  • Unlocking the Potential of Binary Search Trees with C# Programming

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!