Java Collect映射已排序流的顺序/位置值

Java Collect映射已排序流的顺序/位置值,java,java-8,java-stream,collectors,Java,Java 8,Java Stream,Collectors,我正在使用预定义的myComparator对流中填充的一组MyObject(该对象有一个getName()getter)进行排序 然后,一旦排序,是否有方法将MyObject的名称和排序中对象的顺序/位置收集到地图中 我认为它应该是这样的: Set<MyObject> mySet; // Already populated mySet Map<String, Integer> nameMap = mySet.stream() .sorted(myCo

我正在使用预定义的myComparator对流中填充的一组MyObject(该对象有一个getName()getter)进行排序

然后,一旦排序,是否有方法将MyObject的名称和排序中对象的顺序/位置收集到地图中

我认为它应该是这样的:

Set<MyObject> mySet;  // Already populated mySet 

Map<String, Integer> nameMap = mySet.stream()
        .sorted(myComparator)
        .collect(Collectors.toMap(MyObject::getName, //HowToGetThePositionOfTheObjectInTheStream));

谢谢。

Java
不会公开元素的任何索引或位置,因此我不知道如何用streams magic替换
/*如何设置对象在streams*/
中的位置以获得所需的数字

相反,一种简单的方法是收集到一个
列表
,它为每个元素提供一个索引。它是基于零的,所以当转换为地图时,添加1

List<String> inOrder = mySet.stream()
     .sorted(myComparator)
     .map(MyObject::getName)
     .collect(Collectors.toList());
Map<String, Integer> nameMap = new HashMap<>();
for (int i = 0; i < inOrder.size(); i++) {
    nameMap.put(inOrder.get(i), i + 1);
}
List inoorder=mySet.stream()
.已排序(myComparator)
.map(MyObject::getName)
.collect(Collectors.toList());
Map nameMap=newhashmap();
for(int i=0;i
试试这个。您可以使用
AtomicInteger
作为映射的每个条目的值。同时,为了保证地图的使用顺序,请使用
LinkedHashMap

AtomicInteger index = new AtomicInteger(1);
Map<String, Integer> nameMap =  mySet.stream()
    .sorted(myComparator)
    .collect(Collectors
            .toMap(MyObject::getName, value -> index.getAndIncrement(),
                  (e1, e2) -> e1, LinkedHashMap::new));
AtomicInteger索引=新的AtomicInteger(1);
Map nameMap=mySet.stream()
.已排序(myComparator)
.收藏(收藏家)
.toMap(MyObject::getName,value->index.getAndIncrement(),
(e1,e2)->e1,LinkedHashMap::new);
不要使用流:

List<MyObject> list = new ArrayList<>(mySet);
list.sort(myComparator);
Map<String, Integer> nameMap = new HashMap<>();
for (int i = 0; i < list.size(); i++) {
    nameMap.put(list.get(i).getName(), i);
}
List List=newarraylist(mySet);
list.sort(myComparator);
Map nameMap=newhashmap();
对于(int i=0;i
这不仅会比基于流的方法执行得更快,而且每个人都知道发生了什么


流有自己的位置,但Java 8之前的代码也有。最简单的解决方案是循环,因为一个形式正确的流解决方案也可以并行工作,需要一个非平凡的合并函数(与其他函数相比):

Map<String,Integer> nameMap = mySet.stream()
    .sorted(myComparator)
    .collect(HashMap::new, (m, s) -> m.put(s.getName(), m.size()),
        (m1, m2) -> {
            int offset = m1.size();
            m2.forEach((k, v) -> m1.put(k, v + offset));
    });

使用树形图:@CardinalSystem
TreeMap
help到底有什么帮助?@lexicore我误解了这个问题。虽然他要的是分类地图,但我想我同意你的看法。我原本以为可能有一个功能可以公开定位,但在线搜索则不然。感谢您的回答。OP不关心地图的顺序,只关心它的条目;使用do的常规toMap。这将并行失败。循环可以更简单:
for(MyObject o:list)nameMap.put(o.getName(),nameMap.size())
Map<String,Integer> nameMap = mySet.stream()
    .sorted(myComparator)
    .collect(HashMap::new, (m, s) -> m.put(s.getName(), m.size()),
        (m1, m2) -> {
            int offset = m1.size();
            m2.forEach((k, v) -> m1.put(k, v + offset));
    });
List<MyObject> ordered = new ArrayList<>(mySet);
ordered.sort(myComparator);
Map<String, Integer> result = new HashMap<>();
for(MyObject o: ordered) result.put(o.getName(), result.size());
for(MyObject o: ordered)
    if(result.putIfAbsent(o.getName(), result.size()) != null)
        throw new IllegalStateException("duplicate " + o.getName());