Java 8 Streams:分析相同的列表元素

时间:2015-06-29 16:44:06

标签: java lambda java-8 java-stream

代码解释得更好:

测试用例

var gridOptions = { autoHeight:true };

必需的解决方案(无流):

@org.junit.Test
public void test() {
    List<Integer> values = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

    System.out.println(withoutStreams(values)); // Output: 1,9
    System.out.println(withStreamSol1Error(values)); // Compile time error
    System.out.println(withStreamSol2(values)); // Output: 1,9
}

我的尝试:使用Stream :(编译时间错误 - 不匹配)

private List<Integer> withoutStreams(List<Integer> values) {
    // List<Integer> values = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

    for (int index1 = 0; index1 < values.size(); index1++) {
        int value1 = values.get(index1);
        if (value1 == 10)
            return Arrays.asList(value1);
        for (int index2 = index1 + 1; index2 < values.size(); index2++) {
            int value2 = values.get(index2);

            if ((value1 + value2) == 10) {
                return Arrays.asList(value1, value2);
            }
        }
    }

    return Collections.emptyList();
}

使用流(工作)

private List<Integer> withStreamSol1Error(List<Integer> values) {
    List<Integer> exactEqual = values.stream().filter(value -> value.intValue() == 10).limit(1)
            .collect(Collectors.toList());

    // Compile Time Error
    if (exactEqual.isEmpty()) {
        IntStream.range(0, values.size() - 1)
                .forEachOrdered(index -> IntStream.range(index + 1, values.size() - 1)
                        .filter(index2 -> values.get(index) + values.get(index2) == 10).limit(1)
                        .collect(Collectors.toList()));
    }

    return Collections.emptyList();
}

有人能为这个问题提出一个好的解决方案吗?

2 个答案:

答案 0 :(得分:0)

private static List<Integer> withStreamSol1(List<Integer> values) {
    List<Integer> result = new ArrayList<>();
    values.stream()
        .filter(i -> result.isEmpty() && i == 10)
        .forEach(i -> result.add(i));
    IntStream.range(0, values.size())
        .filter(i -> result.isEmpty())
        .forEach(i -> IntStream.range(i + 1, values.size())
            .filter(j -> result.isEmpty() && values.get(i) + values.get(j) == 10)
            .forEach(j -> result.addAll(Arrays.asList(values.get(i), values.get(j)))));
    return result;
}

或者

private static Stream<int[]> streamOfOneOrTwoElements(List<Integer> list) {
    return Stream.concat(
        list.stream()
            .map(i -> new int[] {i}),
        IntStream.range(0, list.size())
            .boxed()
            .flatMap(i -> IntStream.range(i + 1, list.size())
                .mapToObj(j -> new int[] {list.get(i), list.get(j)})));
}

private static List<Integer> withStreamSol3(List<Integer> values) {
    Optional<int[]> array = streamOfOneOrTwoElements(values)
        .filter(a -> IntStream.of(a).sum() == 10)
        .findFirst();
    return array.isPresent()
        ? IntStream.of(array.get()).boxed().collect(Collectors.toList())
        : Collections.emptyList();
}

答案 1 :(得分:0)

稍微简短的解决方案:

static List<Integer> withStreams2(List<Integer> values) {
    return IntStream.range(0, values.size()).boxed()
        .flatMap(
            idx1 -> Stream.concat(Stream.of(Collections.singletonList(values.get(idx1))),
                    IntStream.range(idx1+1, values.size()).mapToObj(
                       idx2 -> Arrays.asList(values.get(idx1), values.get(idx2)))))
        .filter(list -> list.stream().mapToInt(Integer::intValue).sum() == 10)
        .findFirst().orElse(Collections.emptyList());
}