如何在 Java 流中配对不均匀列表

我有一个点列表和点之间的距离,我想要做的是创建段,其中段由起点和终点以及两点之间的距离组成。


使用简单的 for 循环,我可以执行以下操作:


public static void main(String[] args) {

    List<String> points = Arrays.asList("A", "B", "C", "D");

    List<Double> distances = Arrays.asList(1.5, 2.5, 3.5);


    for(int x=0; x< distances.size(); x++) {

        new Segment(points.get(x), points.get(x+1), distances.get(x));

    }

}


static class Segment {

    private String startPoint;

    private String endPoint;

    private double distance;


    public Segment(String startPoint, String endPoint, double distance)

    {

        this.startPoint = startPoint;

        this.endPoint = endPoint;

        this.distance = distance;

    }

}

但是,是否有一种不错的方法可以对不会增加代码复杂性的流执行相同的操作?


墨色风雨
浏览 127回答 3
3回答

慕码人2483693

要使用流来做这件事,你最终会做同样的事情,即迭代索引值:List<Segment> list = IntStream.range(0, distances.size())&nbsp; &nbsp; &nbsp; &nbsp; .mapToObj(x -> new Segment(points.get(x), points.get(x+1), distances.get(x)))&nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());是相同的:List<Segment> list = new ArrayList<>();for (int x = 0; x < distances.size(); x++)&nbsp; &nbsp; list.add(new Segment(points.get(x), points.get(x+1), distances.get(x)));除非new Segment()速度很慢并且可以从并行处理中受益,否则使用流没有任何好处,而且它实际上运行得更慢。

森栏

你可以用流做这样的事情:if (points.size() - distances.size() != 1) throw new IllegalArgumentException();List<Segment> path = IntStream.range(0, distances.size())&nbsp; &nbsp; .mapToObj(x -> new Segment(points.get(x), points.get(x + 1), distances.get(x)))&nbsp; &nbsp; .collect(Collectors.toList());它是增加了清晰度,还是模糊了功能?

守着一只汪

虽然我同意其他人的观点,即基于 Stream 的解决方案很可能更难阅读,但如果您经常使用它们或者可以从对它们应用复杂处理中受益,那么投资它们可能仍然值得。我将添加一个非基于 IntStream 的方法,以防您可以在此处或在未来的项目中应用它:public static Stream<Segment> zip(List<String> points, List<Double> distances){&nbsp; &nbsp; if (points == null || distances == null || points.size() - 1 != distances.size())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; throw new IllegalArgumentException();&nbsp; &nbsp; }&nbsp; &nbsp; return StreamSupport.stream(new AbstractSpliterator<Segment>(distances.size(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Spliterator.ORDERED | Spliterator.SIZED)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; private Iterator<String> pointsIterator&nbsp; &nbsp; = points.iterator();&nbsp; &nbsp; &nbsp; &nbsp; private Iterator<Double> distancesIterator = distances.iterator();&nbsp; &nbsp; &nbsp; &nbsp; private String&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;previousPoint&nbsp; &nbsp; &nbsp;= this.pointsIterator.next();&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public boolean tryAdvance(Consumer<? super Segment> action)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!pointsIterator.hasNext())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action.accept(new Segment(previousPoint,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (previousPoint = pointsIterator.next()),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; distancesIterator.next()));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }, false);}zip(points, distances).forEach(System.out::println)// Segment [startPoint=A, endPoint=B, distance=1.5]// Segment [startPoint=B, endPoint=C, distance=2.5]// Segment [startPoint=C, endPoint=D, distance=3.5]我使用AbstractSpliterator最准系统的实现并将其包装到流中。您可以trySplit在这里公平地实现每个,以利用并行性并通过实现forEachRemaining. 如果您有兴趣,我可以添加这些。虽然这种方法肯定是一堆阅读,但使用它非常容易,因为它对开发人员隐藏了流创建。请注意,您可以通过使用 while 循环,在没有流的情况下使用相同的基于迭代器的技术。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java