为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用流获取嵌套集合中的所有元素

如何使用流获取嵌套集合中的所有元素

慕尼黑8549860 2022-12-28 10:48:58
我有一个包含不同嵌套集合的类,现在我想接收嵌套集合的所有元素,具体我想收集集合的所有 StrokePoints。我可以用“旧的”java 来解决它,但是如何用流来解决呢?    int strokesCounter = 0;    List<StrokePoint> pointList = new ArrayList<>();    if (!strokesData.getListOfSessions().isEmpty()) {        for (SessionStrokes session : strokesData.getListOfSessions()) {            List<Strokes> strokes = session.getListOfStrokes();            for (Strokes stroke : strokes) {                strokesCounter++;                List<StrokePoint> points = stroke.getListOfStrokePoints();                pointList.addAll(stroke.getListOfStrokePoints());                    }        }    }我正在寻找一种使用流功能填充 pointList 的方法。
查看完整描述

4 回答

?
波斯汪

TA贡献1811条经验 获得超4个赞

展平嵌套数据非常简单:

List<StrokePoint> pointList = strokesData.getListOfSessions()
        .streams()
        .map(SessionStrokes::getListOfStrokes)
        .flatMap(List::stream)
        .map(Strokes::getListOfStrokePoints)
        .flatMap(List::stream)
        .collect(Collectors.toList());

沿途收集划水次数比较棘手,而且有些争议。你可以创建一个

AtomicInteger strokesCounter = new AtomicInteger();

并在第一个之后增加它flatMap

.peek(strokesCounter::incrementAndGet)


查看完整回答
反对 回复 2022-12-28
?
白板的微信

TA贡献1883条经验 获得超3个赞

你可以只使用Stream.flatMap()两次:

List<StrokePoint> pointList = strokesData.getListOfSessions().stream()
        .flatMap(session -> session.getListOfStrokes().stream())
        .flatMap(strokes -> strokes.getListOfStrokePoints().stream())
        .collect(Collectors.toList());

如果您需要计算笔画列表,您可以将其分成两部分并使用List.size()

List<Strokes> strokesList = strokesData.getListOfSessions().stream()
        .flatMap(session -> session.getListOfStrokes().stream())
        .collect(Collectors.toList());int strokesCounter = strokesList.size();
List<StrokePoint> pointList = strokesList.stream()
        .flatMap(strokes -> strokes.getListOfStrokePoints().stream())
        .collect(Collectors.toList());

或者你可以增加一个AtomicIntegerin flatMap()

final AtomicInteger strokesCounter = new AtomicInteger();
List<StrokePoint> pointList = strokesData.getListOfSessions().stream()
        .flatMap(session -> {
            List<Strokes> strokes = session.getListOfStrokes();
            strokesCounter.addAndGet(strokes.size());   
                     return strokes.stream();
        })
        .flatMap(strokes -> strokes.getListOfStrokePoints().stream())
        .collect(Collectors.toList());

或与peek()

final AtomicInteger strokesCounter = new AtomicInteger();
List<StrokePoint> pointList = strokesData.getListOfSessions().stream()
        .flatMap(session -> session.getListOfStrokes().stream())
        .peek(i -> strokesCounter.incrementAndGet())
        .flatMap(strokes -> strokes.getListOfStrokePoints().stream())
        .collect(Collectors.toList());


查看完整回答
反对 回复 2022-12-28
?
慕后森

TA贡献1802条经验 获得超5个赞

由于主要目的是解决收集 的问题List<StrokePoint>,您可以使用以下flatMap操作执行它:


List<StrokePoint> points = strokesData.getListOfSessions()

        .stream()

        .flatMap(ss -> ss.getListOfStrokes().stream()

                .flatMap(s -> s.getListOfStrokePoints().stream()))

        .collect(Collectors.toList());

此外,Strokes 的计数也可以通过对列表的大小求和来使用流来计算:


long strokeCount = strokesData.getListOfSessions()

        .stream()

        .mapToLong(ss -> ss.getListOfStrokes().size())

        .sum();

要合并这些操作,您可以构造AbstractMap.SimpleEntrywhile 减少条目为:


AbstractMap.SimpleEntry<Integer, Stream<StrokePoint>> reduce = strokesData.getListOfSessions()

        .stream()

        .map(ss -> new AbstractMap.SimpleEntry<>(ss.getListOfStrokes().size(),

                ss.getListOfStrokes()

                        .stream()

                        .flatMap(s -> s.getListOfStrokePoints().stream())))

        .reduce(new AbstractMap.SimpleEntry<>(1, Stream.empty()),

                (e1, e2) -> new AbstractMap.SimpleEntry<>(

                        Integer.sum(e1.getKey(), e2.getKey()),

                        Stream.concat(e1.getValue(), e2.getValue())));

使用此条目,您可以获得 s 的计数和Strokes 的列表StrokePoint:


long strokeCount = reduce.getKey();

List<StrokePoint> strokePoints = reduce.getValue().collect(Collectors.toList());


查看完整回答
反对 回复 2022-12-28
?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

如果您担心副作用,这样做就可以了(但是在撰写本文时其他两个答案都更具可读性):


    Entry<Integer, List<StrokePoint>> summary = //

            strokesData.getListOfSessions()

                       .stream()

                       .flatMap(session -> session.getListOfStrokes().stream())

                       .map(strokes -> new SimpleEntry<>(1, strokes.getListOfStrokePoints()))

                       .reduce((l1, l2) -> {

                           int count = l1.getKey() + l2.getKey();


                           List<StrokePoint> list = l1.getValue();

                           list.addAll(l2.getValue());


                           return new SimpleEntry<>(count, list);

                       })

                       .orElse(new SimpleEntry<>(0, Collections.emptyList()));


    strokesCounter = summary.getKey();

    pointList = summary.getValue();

编辑以添加验证:


public class Scratch {

    public static void main(String[] args) {

        int strokesCounter = 0;

        List<StrokePoint> pointList = new ArrayList<>();

        StrokesData strokesData = new StrokesData();


        SessionStrokes sessionStrokes = new SessionStrokes();

        strokesData.sessionStrokes.add(sessionStrokes);


        Strokes s1 = new Strokes();

        sessionStrokes.strokesList.add(s1);


        s1.strokePoints.add(new StrokePoint());

        s1.strokePoints.add(new StrokePoint());


        Strokes s2 = new Strokes();

        sessionStrokes.strokesList.add(s2);


        s2.strokePoints.add(new StrokePoint());

        s2.strokePoints.add(new StrokePoint());

        s2.strokePoints.add(new StrokePoint());

        s2.strokePoints.add(new StrokePoint());

        s2.strokePoints.add(new StrokePoint());

        s2.strokePoints.add(new StrokePoint());


        Entry<Integer, List<StrokePoint>> summary = //

                strokesData.getListOfSessions()

                           .stream()

                           .flatMap(session -> session.getListOfStrokes()

                                                      .stream())

                           .map(strokes -> new SimpleEntry<>(1, strokes.getListOfStrokePoints()))

                           .reduce((l1, l2) -> {

                               int count = l1.getKey() + l2.getKey();


                               List<StrokePoint> list = l1.getValue();

                               list.addAll(l2.getValue());


                               return new SimpleEntry<>(count, list);

                           })

                           .orElse(new SimpleEntry<>(0, Collections.emptyList()));


        strokesCounter = summary.getKey();

        pointList = summary.getValue();


        System.out.println(strokesCounter);

        System.out.println(pointList);

    }

}


class StrokesData {


    List<SessionStrokes> sessionStrokes = new ArrayList<>();


    public List<SessionStrokes> getListOfSessions() {

        return sessionStrokes;

    }

}


class SessionStrokes {


    List<Strokes> strokesList = new ArrayList<>();


    public List<Strokes> getListOfStrokes() {

        return strokesList;

    }


}


class Strokes {


    List<StrokePoint> strokePoints = new ArrayList<>();


    public List<StrokePoint> getListOfStrokePoints() {

        return strokePoints;

    }

}


class StrokePoint {

}


查看完整回答
反对 回复 2022-12-28
  • 4 回答
  • 0 关注
  • 133 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号