分组对象java 8

时间:2016-04-06 07:55:46

标签: java java-8 java-stream

我有类似下面的内容:

public class MyClass {
private Long stackId
private Long questionId
}

说100的集合,其中stackid可以与不同的questionId重复。它是stackId和questionId之间的一对多关系

是否有简洁,java 8方式转换为以下strcuture:

public class MyOtherClass {
private Long stackId
private Collection<Long> questionIds
}

这是25的集合,每个实例都有4个questionIds的嵌套集合。

输入:

[{1,100},{1,101},{1,102},{1,103},{2,200},{2,201},{2,202},{1,203}]

输出

[{1, [100,101,102,103]},{2,[200,201,202,203]}]

3 个答案:

答案 0 :(得分:9)

Stream API的直接方式涉及2个流管道:

  • 第一个创建Map<Long, List<Long>> stackIdquestionIds的临时stackId。这是通过我们根据stackId进行分类的groupingBy(classifier, downstream)收藏家完成的,具有相同questionId的值会映射到他们的MyOtherClass(带mapping)并收集到toList()的列表中。
  • 第二个将该地图的每个条目转换为MyOtherClass(Long stackId, Collection<Long> questionIds)个实例,并将其收集到一个列表中。

假设您有一个构造函数Map<Long, List<Long>> map = list.stream() .collect(Collectors.groupingBy( MyClass::getStackId, Collectors.mapping(MyClass::getQuestionId, Collectors.toList()) )); List<MyOtherClass> result = map.entrySet() .stream() .map(e -> new MyOtherClass(e.getKey(), e.getValue())) .collect(Collectors.toList()); ,示例代码为:

stackId

使用StreamEx库,您可以在单个Stream管道中执行此操作。此库提供pairingfirst收藏家。这样可以将两个收集器配对并对两个收集的结果执行修整器操作:

  • 第一个只保留分组元素的第一个questionId(它们将通过构造全部相同)
  • 第二个将每个元素映射到MyOtherClass并收集到列表中。
  • 整理器操作只返回import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.mapping; import static java.util.stream.Collectors.toList; import static one.util.streamex.MoreCollectors.first; import static one.util.streamex.MoreCollectors.pairing; // ... Collection<MyOtherClass> result = StreamEx.of(list) .groupingBy( MyClass::getStackId, pairing( collectingAndThen(mapping(MyClass::getStackId, first()), Optional::get), mapping(MyClass::getQuestionId, toList()), MyOtherClass::new ) ).values();
  • 的新实例

示例代码:

<appSettings configSource="appSettings.config"/>;

答案 1 :(得分:2)

onCreate()

答案 2 :(得分:0)

您可以使用java8 groupingBy收集器。像这样:

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class RandomTest {

    class MyClass {
        private Long stackId;
        private Long questionId;

        public MyClass(Long stackId, Long questionId) {
            this.stackId = stackId;
            this.questionId = questionId;
        }

        public Long getStackId() {
            return stackId;
        }

        public Long getQuestionId() {
            return questionId;
        }
    }

    public class MyOtherClass {
        private Long stackId;
        private Set<Long> questionIds;

        public MyOtherClass(Long stackId, Set<Long> questionIds) {
            this.stackId = stackId;
            this.questionIds = questionIds;
        }

        public Long getStackId() {
            return stackId;
        }

        public Set<Long> getQuestionIds() {
            return questionIds;
        }
    }

    @Test
    public void test() {
        List<MyClass> classes = new ArrayList<>();
        List<MyOtherClass> otherClasses = new ArrayList<>();

        //populate the classes list
        for (int j = 1; j <= 25; j++) {
            for (int i = 0; i < 4; i++) {
                classes.add(new MyClass(0L + j, (100L*j) + i));
            }
        }

        //populate the otherClasses List
        classes.stream().collect(Collectors
                .groupingBy(MyClass::getStackId, Collectors.mapping(MyClass::getQuestionId, Collectors.toSet())))
                .entrySet().stream().forEach(
                longSetEntry -> otherClasses.add(new MyOtherClass(longSetEntry.getKey(), longSetEntry.getValue())));

        //print the otherClasses list
        otherClasses.forEach(myOtherClass -> {
            System.out.print(myOtherClass.getStackId() + ": [");
            myOtherClass.getQuestionIds().forEach(questionId-> System.out.print(questionId + ","));
            System.out.println("]");
        });
    }
}