在一组对象中查找连续的String属性序列(通过流API)

时间:2019-05-06 12:14:57

标签: java java-8 java-stream

我必须编写一个采用SortedSet<MyEvent>List<String>的方法。它必须确定是否存在由某个类属性表示给定MyEvent的{​​{1}}的连续序列。

假设存在以下(代码)情况:

List<String>

和一个List<String> list = new ArrayList<String>() list.add("AAA"); list.add("BBB");

Set<MyEvent>

具有SortedSet<MyEvent> events = new TreeSet<MyEvent>(); 类型的MyEvent对象(仅与implements Comparable<MyEvent>比较)。
给定的LocalDateTime代表一个缩写序列,我需要查找最近出现的List<String>序列,其类属性MyEvent具有该序列的值。

这是我到目前为止所做的:

abbreviation

该方法有效(至少对于此2元素序列而言)。

  

是否可以使用流API在一次调用中完成此操作(序列大小未知)?

2 个答案:

答案 0 :(得分:3)

您的任务并不难,只需创建一个Stream,应用一个filter,然后索取最大值。在谓词中需要一个前一个元素是有障碍的,但是我们可以动手使用可以提供它的源集合。

实际上,每个SortedSet也是一个NavigableSet,它提供了一种lower方法来获取前一个元素(如果有),但是由于您的要求是支持{{ 1}}输入,我们必须为SortedSet不是SortedSet的理论情况提供后备。

然后,该操作可以实现为

NavigableSet

但是我们可以做得更好。由于我们现在正在搜索 sorted 输入中的最大值,因此我们知道向后迭代时,第一个匹配就足够了。同样,当输入实际上是public static MyEvent getMostRecentLastEventOfSequence( SortedSet<MyEvent> events, List<String> sequence) { String first = sequence.get(0), second = sequence.get(1); UnaryOperator<MyEvent> previous; if (events instanceof NavigableSet) { NavigableSet<MyEvent> navigableSet = (NavigableSet<MyEvent>) events; previous = navigableSet::lower; } else previous = event -> events.headSet(event).last(); return events.stream() .filter(event -> event.getAbbreviation().equals(second)) .filter(event -> { MyEvent p = previous.apply(event); return p != null && p.getAbbreviation().equals(first); }) .max(Comparator.naturalOrder()).orElse(null); } 时,会更加平滑:

NavigableSet

因此,此方法将向后搜索并在第一个匹配项处停止,该匹配项已经是最大元素,而无需遍历所有元素。

答案 1 :(得分:1)

另一个解决方案是使用索引。序列的大小不限于2。

Private Sub PurchaseOrder_BeforeUpdate(Cancel As Integer)

    Cancel = IsNull(Me!PurchaseOrder.Value)

End Sub

这是示例测试代码:

public static MyEvent getMostRecentLastEventOfSequence(SortedSet<MyEvent> events, List<String> sequence) {
  final List<MyEvent> eventList = new ArrayList<>(events);
  Collections.reverse(eventList);
  final int seqLength = sequence.size();

  OptionalInt first = IntStream.range(0, eventList.size() - seqLength + 1)
      .filter(i -> IntStream.range(0, seqLength)
          .allMatch(j -> eventList.get(i + j).getAbbreviation().equals(sequence.get(seqLength - j - 1))))
      .findFirst();

  return first.isPresent() ? eventList.get(first.getAsInt()) : null;
}

带有@Test void test_56005015() throws Exception { List<String> sequence = Arrays.asList("AAA", "BBB", "CCC"); SortedSet<MyEvent> events = new TreeSet<>(); events.add(new MyEvent("AAA", LocalDateTime.now().plusDays(1))); events.add(new MyEvent("BBB", LocalDateTime.now().plusDays(2))); events.add(new MyEvent("CCC", LocalDateTime.now().plusDays(3))); events.add(new MyEvent("AAA", LocalDateTime.now().plusDays(4))); events.add(new MyEvent("BBB", LocalDateTime.now().plusDays(5))); events.add(new MyEvent("CCC", LocalDateTime.now().plusDays(6))); MyEvent result = getMostRecentLastEventOfSequence(events, sequence); System.out.println(result); } 类并带有MyEvent的注释。

Lombok