当前位置: 首页 > 知识库问答 >
问题:

如何通过Java流API获得一个以某个匹配开始、以不同匹配结束的子列表?

狄易安
2023-03-14

我对从有序对象列表中获取子列表的streamY方法感兴趣。子列表应该以一个对象开始,该对象匹配一个与它的属性相关的给定条件,它应该以一个对象匹配一个不同的条件结束。

假设我有以下类element:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Element implements Comparable<Element> {

    String abbreviation;
    LocalDateTime creationTime;

    public Element(String abbreviation, LocalDateTime creationTime) {
        this.abbreviation = abbreviation;
        this.creationTime = creationTime;
    }

    public String getAbbreviation() {
        return abbreviation;
    }

    public void setAbbreviation(String abbreviation) {
        this.abbreviation = abbreviation;
    }

    public LocalDateTime getCreationTime() {
        return creationTime;
    }

    public void setCreationTime(LocalDateTime creationTime) {
        this.creationTime = creationTime;
    }

    @Override
    public int compareTo(Element otherElement) {
        return this.creationTime.compareTo(otherElement.getCreationTime());
    }

    @Override
    public String toString() {
        return "[" + abbreviation + ", "
                + creationTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + "]";
    }
}
private static List<Element> generateSomeElements() {
    List<Element> elements = new ArrayList<Element>();

    LocalDateTime now = LocalDateTime.now();

    Element elementOne = new Element("ABC", now.minus(14, ChronoUnit.DAYS));
    Element elementTwo = new Element("DEF", now.minus(13, ChronoUnit.DAYS));
    Element elementThree = new Element("GHI", now.minus(12, ChronoUnit.DAYS));
    Element elementFour = new Element("JKL", now.minus(11, ChronoUnit.DAYS));
    Element elementFive = new Element("MNO", now.minus(10, ChronoUnit.DAYS));
    Element elementSix = new Element("PQR", now.minus(9, ChronoUnit.DAYS));
    Element elementSeven = new Element("STU", now.minus(8, ChronoUnit.DAYS));
    Element elementEight = new Element("VWX", now.minus(7, ChronoUnit.DAYS));
    Element elementNine = new Element("YZ1", now.minus(6, ChronoUnit.DAYS));
    Element elementTen = new Element("234", now.minus(5, ChronoUnit.DAYS));

    elements.add(elementOne);
    elements.add(elementTwo);
    elements.add(elementThree);
    elements.add(elementFour);
    elements.add(elementFive);
    elements.add(elementSix);
    elements.add(elementSeven);
    elements.add(elementEight);
    elements.add(elementNine);
    elements.add(elementTen);

    return elements;
}

我需要从(包括)“mno”到(包括)“yz1”的子列表,保持它在源列表中的顺序,将创建时间放在一边。

我知道如何在不使用流的情况下做到这一点(比如查找开始和结束的索引,然后将元素从indexstart获取到indexend),这可能已经足够了,但有些过时,不能真正满足我对使用现代API的渴望。

我可以添加我使其工作的方法,但它们只是描述问题的另一种形式,而我无法使用单个stream-statement来解决这个问题。此外,这些方法在许多不同的问题中得到了解释,这些问题要求提供一个一般的可能性,而不是以流API为目标。

一般情况下:
有两个条件和一个list ,其中要收集一个子列表,它的第一个元素是一个匹配条件1,它的最后一个元素是一个匹配条件2,同时收集这两个元素之间的所有元素,并且顺序保持原点不变。

因此,如果您知道用一个stream API语句获得所需子列表的可能性,请添加它作为答案。

同时我会看看reduce()方法,也许这就是谜底的答案…

编辑
我找到了一个解决方案,它使用stream()调用给出了所需的结果,但我需要三个。一个获取与第一个条件匹配的元素,另一个找到与第二个条件匹配的元素,然后一个使用前两个流()s中找到的两个元素的creationtimes获取所需子列表:

public static void main(String[] args) {
    List<Element> elements = generateSomeElements();

    // print origin once followed by a horizontal separator for the human eye
    elements.forEach(element -> System.out.println(element.toString()));

    System.out.println("————————————————————————————————");

    // find the reference object which should be the first element of the desired
    // sublist
    Element fromIncluding = elements.stream()
            .filter(element -> element.getAbbreviation().equals("MNO")).findFirst()
            .get();
    Element toIncluding = elements.stream()
            .filter(element -> element.getAbbreviation().equals("YZ1")).findFirst()
            .get();

    List<Element> mnoToYz1 = elements.stream()
            .filter(element ->
                (element.getCreationTime().isAfter(fromIncluding.getCreationTime())
                    && element.getCreationTime().isBefore(toIncluding.getCreationTime()))
                || element.getCreationTime().isEqual(fromIncluding.getCreationTime())
                || element.getCreationTime().isEqual(toIncluding.getCreationTime()))
            .collect(Collectors.toList());

    mnoToYz1.forEach(element -> System.out.println(element.toString()));
}

共有1个答案

徐杰
2023-03-14

如果输入列表是有序的,获取子列表的另一种方法是使用范围而不是示例中的对象比较:

int fromIncluding = IntStream.range(0, elements.size())
    .filter(i -> elements.get(i).getAbbreviation().equals("MNO"))
    .findFirst().orElse(0);
int toIncluding = IntStream.range(fromIncluding, elements.size())
    .filter(i -> elements.get(i).getAbbreviation().equals("YZ1"))
    .findFirst().orElse(elements.size() - 1);

List<Element> mnoToYz1 = elements.subList(fromIncluding, toIncluding+1);
 类似资料:
  • 我的目标是得到两个匹配: 非常感谢你的帮助。

  • 我有一个接口,它提供了一个方法,返回一个,其中包含一个

  • 当Callable返回与条件匹配的结果时,是否有一种方法可以停止Javas ExecuterService? 我有以下算法(代码A): 平均而言,functionB的运行速度是functionA的5倍(在8个内核上)。 这很好,但不完美。在functionA中,someFunction()在找到结果!=null之前平均被调用大约20次。在functionB中,someFunction()总是被调用

  • 问题内容: 我有一个正则表达式,用于匹配表格的表达式 这个正则表达式看起来像: 正如您在本演示中看到的那样,这实际上很好,并且与我想要的匹配 但是:D(黄油来了) 我想通过使其更易读和“紧凑”来优化正则表达式本身。我搜索了如何执行此操作,然后找到了一种称为反向引用的名称,您可以在其中命名捕获组,然后像下面这样引用它们: 我在其中命名了捕获表达式左侧的组,后来我将其引用为,现在的 问题 是,仅在表达

  • 我有一些字符串,比如: 我的目标是使用一个RegEx来匹配以开始而不是以结束的所有字符串。我怎么写?

  • 我正在为我的 REST API 控制器编写测试,我需要检查返回的 对象中的 值,请参阅此测试方法: 但是测试产生了这个错误: 似乎ID被正确返回,但被序列化为不同的结构。 我的代码有什么问题?