Idiomatic enumeration of an object stream in Java 8

How can I idiomatically enumerate a Stream<T>that matches each instance Twith a unique integer using Java 8 stream methods (e.g. for an array T[] values), creating Map<T,Integer>where it Map.get(values[i]) == ievaluates to true)?

I am currently defining an anonymous class that increments a field intfor use with a method Collectors.toMap(..):

private static <T> Map<T, Integer> createIdMap(final Stream<T> values) {
    return values.collect(Collectors.toMap(Function.identity(), new Function<T, Integer>() {

        private int nextId = 0;

        @Override
        public Integer apply(final T t) {
            return nextId++;
        }

    }));
}

However, is there a more concise / elegant way to do this using the Java 8 thread API? - bonus points if they can be safely parallelized.

+4
source share
3 answers

, .

, , Mutable reduction. , , .

- . , .

private static <T> Map<T, Integer> createIdMap(Stream<T> values) {
    return values.collect(HashMap::new, (m,t) -> m.putIfAbsent(t,m.size()),
        (m1,m2) -> {
            if(m1.isEmpty()) m1.putAll(m2);
            else m2.keySet().forEach(t -> m1.putIfAbsent(t, m1.size()));
        });
}

distinct(),

private static <T> Map<T, Integer> createIdMap(Stream<T> values) {
    return values.distinct().collect(HashMap::new, (m,t) -> m.put(t,m.size()),
        (m1,m2) -> { int leftSize=m1.size();
            if(leftSize==0) m1.putAll(m2);
            else m2.forEach((t,id) -> m1.put(t, leftSize+id));
        });

}
+5

:

private static <T> Map<T, Integer> createIdMap2(final Stream<T> values) {
    List<T> list = values.collect(Collectors.toList());
    return IntStream.range(0, list.size()).boxed()
            .collect(Collectors.toMap(list::get, Function.identity()));
}

parallelism

   return IntStream.range(0, list.size()).parallel().boxed().
                (...)
+4

, Andremoniy. -, "toList()" "list.get(i)", ,

private static <T> Map<T, Integer> createIdMap2(final Stream<T> values) {
    final MutableInt idx = MutableInt.of(0); // Or: final AtomicInteger idx = new AtomicInteger(0);        
    return values.collect(Collectors.toMap(Function.identity(), e -> idx.getAndIncrement()));
}

Regardless of the question, I believe that a poor design passes threads as parameters in a method.

0
source

Source: https://habr.com/ru/post/1669708/


All Articles