2014-12-12 3 views
3
static <T> Map<T, Integer> assignIds(Collection<T> objects); 

Я хочу написать функцию, которая берет коллекцию уникальных объектов и присваивает каждому другому идентификационный номер. Идентификационные номера должны назначаться последовательно.Назначение уникальных идентификаторов объектам с использованием потоков Java 8

я мог бы легко сделать это с явной петли, как:

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

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

Есть элегантный способ сделать это с новым Java 8 Stream API?

ответ

4

Вот один из способов:

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

выше решение может также использовать parallelStream() вместо stream().

Вот еще один, который работает последовательно:

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; 
} 

Опираясь на ответ ZouZou в ...

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())); 
} 

идиоматических способ сделать это, например, Scala будет использовать zipWithIndex. В Java 8 Streams API такого метода нет, даже метод zip, который вы можете комбинировать с IntStream.

6

Вы можете использовать примитивный итератор для генерации идентификаторов:

static <T> Map<T, Integer> assignIds(Collection<T> objects) { 
    PrimitiveIterator.OfInt iterator = IntStream.iterate(0, x -> x + 1) 
       .limit(objects.size()) 
       .iterator(); 
    return objects.stream().collect(Collectors.toMap(obj -> obj, id -> iterator.next())); 
} 

Вы можете быть заинтересованы, чтобы использовать protonpack библиотеку, которая определяет некоторые вспомогательные методы для потоков (например, как zipWithIndex). Таким образом, это может выглядеть так:

static <T> Map<T, Long> assignIds(Collection<T> objects) { 
    return StreamUtils.zipWithIndex(objects.stream()) 
       .collect(Collectors.toMap(Indexed::getValue, Indexed::getIndex)); 
} 
Смежные вопросы