简体   繁体   English

使用Java 8流为对象分配唯一ID

[英]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. 我想编写一个函数,它接受一组唯一对象,并为每个对象分配一个不同的ID号。 The ID numbers should be assigned sequentially. ID号应按顺序分配。

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 ? 使用新的Java 8 Stream API有一种优雅的方法吗?

You could use a primitive iterator to generate the ids: 您可以使用原始迭代器来生成ID:

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

You might be interested to use the protonpack library which defines some utility methods for Streams (such as zipWithIndex ). 您可能有兴趣使用protonpack库来定义Streams的一些实用方法(例如zipWithIndex )。 So it could looks like this: 所以它看起来像这样:

static <T> Map<T, Long> assignIds(Collection<T> objects) {
    return StreamUtils.zipWithIndex(objects.stream())
                .collect(Collectors.toMap(Indexed::getValue, Indexed::getIndex));
}

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() . 上述解决方案也可以使用parallelStream()而不是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 . 在例如Scala中执行此操作的惯用方法是使用zipWithIndex There's no such method in the Java 8 Streams API, not even a zip method which you could combine with an IntStream . Java 8 Streams API中没有这样的方法,甚至没有可以与IntStream结合使用的zip方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM