收集以映射已排序流

时间:2018-05-25 20:09:23

标签: java java-8 java-stream collectors

我使用预定义的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));

例如,如果集合包含三个对象(object1的名称为name1,object2的名称为name2,object3的名称为name3),并且在流中它们被排序,我如何得到如下所示的结果映射:

name1, 1
name2, 2
name3, 3

感谢。

4 个答案:

答案 0 :(得分:3)

Java Stream不会公开元素的任何索引或位置,因此我无法用流魔法替换/*HowToGetThePositionOfTheObjectInTheStream*/以获得所需的数字。

相反,一种简单的方法是收集到List,它为每个元素提供索引。它是从零开始的,所以在转换为地图时,添加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);
}

答案 1 :(得分:1)

最简单的解决方案是循环,作为一个正式正确的流解决方案,也可以并行工作,需要一个非常重要的(与其余的)合并函数:

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

答案 2 :(得分:0)

试试这个。您可以使用my_function <- function(data, column) { quo_column <- enquo(column) new_col <- paste0(quo_column, "_adjusted")[2] mean_col <- paste0(quo_column, "_meanAdjusted")[2] data %>% mutate(!!new_col := (!!quo_column) + 1) %>% group_by(Species) %>% summarise(!!mean_col := mean(!! rlang::sym(new_col))) } head(my_function(iris, Petal.Length)) # A tibble: 3 x 2 # Species Petal.Length_meanAdjusted # <fct> <dbl> #1 setosa 2.46 #2 versicolor 5.26 #3 virginica 6.55 获取每个地图条目的值。并保证地图使用的顺序AtomicInteger

LinkedHashMap

答案 3 :(得分:0)

不要使用流:

{{1}}

这不仅比基于流的方法执行得更快,而且每个人都知道发生了什么。

Streams占有一席之地,但是Java 8之前的代码也是如此。