Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assign unique IDs to objects using Java 8 streams

static <T> Map<T, Integer> assignIds(Collection<T> objects);

I want to write a function that takes a collection of unique objects and assigns a different ID number to each. The ID numbers should be assigned sequentially.

I could easily do this with an explicit loop like:

Map<T, Integer> ids = new HashMap<>();
int id = 0;

for (T object: objects) {
    ids.put(object, id++);
}

Is there an elegant way to do this with the new Java 8 Stream API?

like image 955
John Kugelman Avatar asked Dec 12 '14 22:12

John Kugelman


People also ask

How do I get unique values from a collection stream?

distinct() returns a stream consisting of distinct elements in a stream. distinct() is the method of Stream interface. This method uses hashCode() and equals() methods to get distinct elements.

What is the use of distinct () in Java 8?

Java Stream distinct() method returns a new stream of distinct elements. It's useful in removing duplicate elements from the collection before processing them.

How do you filter a list of objects using a stream?

Java stream provides a method filter() to filter stream elements on the basis of given predicate. Suppose you want to get only even elements of your list then you can do this easily with the help of filter method. This method takes predicate as an argument and returns a stream of consisting of resulted elements.


1 Answers

Here's one way:

static <T> Map<T, Integer> assignIds(Collection<T> objects) {
    AtomicInteger ai = new AtomicInteger();
    return objects.stream()
                  .collect(Collectors.toMap(o -> o, o -> ai.getAndIncrement()));
}

The above solution could also make use of parallelStream() instead of stream().

Here's another that works sequentially:

static <T> Map<T, Integer> assignIds(Collection<T> objects) {
    Map<T, Integer> result = new HashMap<>();
    objects.stream().forEachOrdered(o -> result.put(o, result.size()));        
    return result;
}

Building upon ZouZou's answer...

static <T> Map<T, Integer> assignIds(Collection<T> objects) {
    OfInt ids = IntStream.range(0, objects.size()).iterator();
    return objects.stream().collect(Collectors.toMap(o -> o, o -> ids.next()));
}

The idiomatic way to do this in for instance Scala would be to use zipWithIndex. There's no such method in the Java 8 Streams API, not even a zip method which you could combine with an IntStream.

like image 148
aioobe Avatar answered Sep 17 '22 23:09

aioobe