Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the two min objects from a set using Java stream

I have a Set of some objects. I need to get the two min objects from the Set.

My example is as follows:

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Example {
     public static void main( String[] args ) {
         SomeObject obj1 = new SomeObject(1);
         SomeObject obj2 = new SomeObject(2);
         SomeObject obj3 = new SomeObject(3);
         Set<SomeObject> set = Stream.of(obj1,obj2,obj3)
                                     .collect(Collectors.toSet());

         SomeObject minObject= set.stream()
                                  .min(Comparator.comparingInt(object->object.getValue()))
                                  .get();
         System.out.println(minObject);
     }
}


class SomeObject{
    private int value;
    SomeObject(int value){
            this.value=value;
    }

    public int getValue() {
        return value;
    }

    @Override
    public String toString() {
        return this.value+"";
    }
}

In my example I can get the min object from this Set based on the value attribute.

So, I need to get the two min values using Java stream operations.

The answers should be fast because in my real program I call this method many times and my sets are very large.

like image 224
xmen-5 Avatar asked Dec 24 '18 19:12

xmen-5


People also ask

How do you find the maximum and minimum of a stream?

To get max or min date from a stream of dates, you can use Comparator. comparing( LocalDate::toEpochDay ) Comparator. The toEpochDay() function returns the count of days since epoch i.e. 1970-01-01.

What does stream of () method in Java?

Stream of(T t) returns a sequential Stream containing a single element. Syntax : static Stream of(T t) Parameters: This method accepts a mandatory parameter t which is the single element in the Stream. Return Value: Stream of(T t) returns a sequential Stream containing the single specified element.

How do you limit a stream in Java?

Syntax : Stream<T> limit(long N) Where N is the number of elements the stream should be limited to and this function returns new stream as output. Exception : If the value of N is negative, then IllegalArgumentException is thrown by the function.

Can we use stream with set in Java?

Being a type of Collection, we can convert a set to Stream using its stream() method.


2 Answers

You can get the second min value as follows:

 set.stream()
    .filter(s -> s.getValue() != minObject.getValue())     
    .min(Comparator.comparingInt(object -> object.getValue()))
    .get();
  • This streams over the set of elements again ensuring that we're ignoring the previous min value via filter.
  • Then we get the min value via min

or you can get both at the same time:

Stream<SomeObject> twoMinValues = set.stream()
                   .sorted(Comparator.comparingInt(object -> object.getValue()))
                   .limit(2);
  • This streams over the set of elements, sorting the entire sequence from smallest to largest and then taking the first two which is definitely less efficient than the above approach due to the behaviour of the "sorted" intermediate operation.

The awnser should be fast because In my real program i call this method many times and my Sets are very Large.

As for needing a "fast" program, I'd recommend that you first try to solve the problem at hand just using the typical imperative approach as in most cases they're faster than using streams.

if it's not much better then "consider" using parallel streams if and only if you know that you can leverage parallelism.

see Should I always use a parallel stream when possible?

like image 99
Ousmane D. Avatar answered Nov 15 '22 04:11

Ousmane D.


You can pass your Set<E> to an instance of NavigableSet<E>, then you can poll the first two (lowest) elements from it :

final NavigableSet<SomeObject> navigableSet = new TreeSet<>(Comparator.comparingInt(SomeObject::getValue));

navigableSet.addAll(set);

final SomeObject firstMin = navigableSet.pollFirst();

final SomeObject secondMin = navigableSet.pollFirst();
like image 31
HPH Avatar answered Nov 15 '22 03:11

HPH