static <T> Map<T, Integer> assignIds(Collection<T> objects);
我想编写一个函数,它接受一组唯一对象,并为每个对象分配一个不同的ID号。 ID号应按顺序分配。
我可以使用明确的循环轻松完成此操作:
Map<T, Integer> ids = new HashMap<>();
int id = 0;
for (T object: objects) {
ids.put(object, id++);
}
是否有一种优雅的方法可以使用新的Java 8 Stream API?
答案 0 :(得分:6)
您可以使用原始迭代器生成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()));
}
您可能有兴趣使用protonpack库来定义Streams的一些实用程序方法(例如zipWithIndex
)。所以它看起来像这样:
static <T> Map<T, Long> assignIds(Collection<T> objects) {
return StreamUtils.zipWithIndex(objects.stream())
.collect(Collectors.toMap(Indexed::getValue, Indexed::getIndex));
}
答案 1 :(得分: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;
}
以邹邹的回答为基础......
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
结合使用。