使用java 8流在已排序的数字列表中查找最长的连续数字

时间:2016-12-27 11:53:31

标签: java java-8 java-stream

我使用传统的for循环编写了一段代码,如下所示。我想重构它以使用java 8流并删除for循环。以下代码的输出应为3,因为这是最长的连续数字列表(4,5和6)

    List<Integer> weekDays = Lists.newArrayList(1, 2, 4, 5, 6);

    List<Integer> consecutiveIntervals = Lists.newArrayList();
    int maxConsecutiveTillNow = 1;
    for (int i = 1; i < weekDays.size(); i++) {
        if (weekDays.get(i) - weekDays.get(i - 1) == 1) {
            maxConsecutiveTillNow++;
        } else {
            consecutiveIntervals.add(maxConsecutiveTillNow);
            maxConsecutiveTillNow = 1;
        }
    }
    consecutiveIntervals.add(maxConsecutiveTillNow);

    System.out.println(consecutiveIntervals.stream()
                                           .max(Integer::compareTo)
                                           .get()
                      );

5 个答案:

答案 0 :(得分:5)

foreach (var item in CourseId) { var cr = new Courses(); cr.ID = item; // Here: db.Entry(cr).State = EntityState.Unchanged; // or alternatively: // db.Courses.Attach(cr); rec.course.Add(cr); } db.Admins.Add(rec); db.SaveChanges(); API不太适合此类问题。几乎不可能以正确的方式跟踪Stream的所见元素。所以你必须选择多个Stream

基于Stuart Marks'个答案之一。

Streams

输出

  

3

答案 1 :(得分:3)

溪流的想法是相互独立地处理流中的项目。该模式的最大好处是可以并行执行,因为流API的设计是并发的(即,您不应该在流的顺序项的处理之间保持状态)。在您的特定任务中,数组的使用是最合适的。

答案 2 :(得分:3)

创建序列列表并将其排序为所有序列列表中的最长序列。

例如,如果有列表[1,2,4,5,6] ,则将其分解为:

  

[[1,2],[4,5,6]]

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

public class NumberSequence {
    public static void main(String[] args) {
        List<Integer> weekDays = Arrays.asList(1, 2, 4, 5, 6);

        List<List<Integer>> allWeekdaySequences = weekDays.stream()
                                                          .collect(
                                                                    (Supplier<List<List<Integer>>>) ArrayList::new,
                                                                    (sequences, currentElement) -> generateCombinedBatchesFor(sequences, currentElement),
                                                                    List::addAll);

        System.out.println(allWeekdaySequences);

        Optional<List<Integer>> longestSequence = allWeekdaySequences.stream()
                                                           .sorted((seq1, seq2) -> seq2.size() - seq1.size())
                                                           .findFirst();

        System.out.println(longestSequence.isPresent() ? longestSequence.get().size() : "Nothing found!!");
    }

    private static void generateCombinedBatchesFor(List<List<Integer>> sequences, Integer currentElement) {
        if (needsNewSequence(sequences, currentElement)) {
            sequences.add(new ArrayList<>());
        }
        getLastSequence(sequences).add(currentElement);
    }

    private static boolean needsNewSequence(List<List<Integer>> sequences, Integer currentElement) {
        return sequences.size() == 0 || !isConsecutiveDay(getLastElement(getLastSequence(sequences)),
                currentElement);
    }

    private static boolean isConsecutiveDay(Integer lastElement, Integer currentElement) {
        return currentElement - lastElement == 1;
    }

    private static Integer getLastElement(List<Integer> lastSequence) {
        return !lastSequence.isEmpty() ? lastSequence.get(lastSequence.size()-1) : -1;
    }

    private static List<Integer> getLastSequence(List<List<Integer>> sequences) {
        return sequences.get(sequences.size()-1);
    }
}

<强>输出

  

3

答案 3 :(得分:2)

为此,您需要部分缩减(批处理),java 8流API不提供。

您可以通过分裂器(类似于this answer)自行实现,也可以使用提供它的库,例如streamex或proton-pack

答案 4 :(得分:2)

如果您不介意使用第三方库,我可能会推荐我的免费StreamEx库,它增强了标准的Stream API,并为操作员提供部分缩减功能:

StreamEx.of(weekDays)
        .collapse((a, b) -> b - a == 1, Collectors.counting())
        .max(Comparator.naturalOrder())

此处collapse是部分缩减运算符。第一个BiPredicate告诉给定的相邻元素对是否应该一起还原或新的还原组应该开始。这里的规则是相邻元素应该相差1.第二个参数是用于执行简化的收集器(这里只是counting()收集器)。所以在collapse之后我们得到了组长度流(输入为2和3)。最后,我们使用标准max()运算符。

StreamEx库与Stream API完全兼容(StreamEx创建的Stream可以用作普通流)。 collapse运算符是懒惰的,非常快且并行友好。