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

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

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

墨色风雨 2021-08-04 17:20:05
我有一个点列表和点之间的距离,我想要做的是创建段,其中段由起点和终点以及两点之间的距离组成。使用简单的 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;    }}但是,是否有一种不错的方法可以对不会增加代码复杂性的流执行相同的操作?
查看完整描述

3 回答

?
慕码人2483693

TA贡献1860条经验 获得超9个赞

要使用流来做这件事,你最终会做同样的事情,即迭代索引值:


List<Segment> list = IntStream.range(0, distances.size())

        .mapToObj(x -> new Segment(points.get(x), points.get(x+1), distances.get(x)))

        .collect(Collectors.toList());

是相同的:


List<Segment> list = new ArrayList<>();

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

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

除非new Segment()速度很慢并且可以从并行处理中受益,否则使用流没有任何好处,而且它实际上运行得更慢。


查看完整回答
反对 回复 2021-08-04
?
森栏

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

你可以用流做这样的事情:


if (points.size() - distances.size() != 1) throw new IllegalArgumentException();

List<Segment> path = IntStream.range(0, distances.size())

    .mapToObj(x -> new Segment(points.get(x), points.get(x + 1), distances.get(x)))

    .collect(Collectors.toList());

它是增加了清晰度,还是模糊了功能?


查看完整回答
反对 回复 2021-08-04
?
守着一只汪

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

虽然我同意其他人的观点,即基于 Stream 的解决方案很可能更难阅读,但如果您经常使用它们或者可以从对它们应用复杂处理中受益,那么投资它们可能仍然值得。


我将添加一个非基于 IntStream 的方法,以防您可以在此处或在未来的项目中应用它:


public static Stream<Segment> zip(List<String> points, List<Double> distances)

{

    if (points == null || distances == null || points.size() - 1 != distances.size())

    {

        throw new IllegalArgumentException();

    }


    return StreamSupport.stream(new AbstractSpliterator<Segment>(distances.size(),

                                                                 Spliterator.ORDERED | Spliterator.SIZED)

    {

        private Iterator<String> pointsIterator    = points.iterator();

        private Iterator<Double> distancesIterator = distances.iterator();


        private String           previousPoint     = this.pointsIterator.next();


        @Override

        public boolean tryAdvance(Consumer<? super Segment> action)

        {

            if (!pointsIterator.hasNext())

            {

                return false;

            }


            action.accept(new Segment(previousPoint,

                                      (previousPoint = pointsIterator.next()),

                                      distancesIterator.next()));

            return true;

        }

    }, 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 循环,在没有流的情况下使用相同的基于迭代器的技术。


查看完整回答
反对 回复 2021-08-04
  • 3 回答
  • 0 关注
  • 126 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信