猿问

使用流交替混合两个列表

我使用循环实现了这个,但我不知道如何使用流来实现。我们得到两个列表,例如 1 2 3 和 4 5 6,混合后结果将是 1 4 2 5 3 6。


public <T> List<T> mixingList(List<T> list1, List<T> list2) {

    List<T> result = new ArrayList<>();


    int maxSize = list1.size() > list2.size() ? list1.size() : list2.size();


    for (int i = 0; i < maxSize; i++) {

        if (i < list1.size()) {

            result.add(list1.get(i));

        }


        if (i < list2.size()) {

            result.add(list2.get(i));

        }

    }


    return result;

}

我为此准备测试。首先有 3 个测试 - 第二个列表大小相同 - 第三个是一个空列表 - 大小不同


@Test

public void shouldReturnShakedList() {

    //given

    List<Integer> list1 = new ArrayList<>(Arrays.asList(1, 3, 5));


    List<Integer> list2 = new ArrayList<>(Arrays.asList(2, 4, 6));


    //when

    List<Integer> results = new ShakeListUtil().mixingList(list1, list2);


    //then

    Assertions.assertThat(results).containsExactly(1, 2, 3, 4, 5, 6);

    Assertions.assertThat(results).hasSize(6);

}


@Test

public void shouldReturnJustList2IfList1IsEmpty() {

    //given

    List<Integer> list1 = new ArrayList<>();


    List<Integer> list2 = new ArrayList<>(Arrays.asList(2, 4, 6));


    //when

    List<Integer> results = new ShakeListUtil().mixingList(list1, list2);


    //then

    Assertions.assertThat(results).containsExactly(2, 4, 6);

    Assertions.assertThat(results).hasSize(3);


}


@Test

public void shouldReturnShakedListIfTheSizeListIsDifferent() {

    //given

    List<Integer> list1 = new ArrayList<>(Arrays.asList(1, 3));


    List<Integer> list2 = new ArrayList<>(Arrays.asList(2, 4, 6));


    //when

    List<Integer> results = new ShakeListUtil().mixingList(list1, list2);


    //then

    Assertions.assertThat(results).containsExactly(1, 2, 3, 4, 6);

    Assertions.assertThat(results).hasSize(5);

}

知道如何在 Java 流上做到这一点吗?


蓝山帝景
浏览 159回答 3
3回答

米琪卡哇伊

这是使用流的解决方案:public static <T> List<T> mixingList(List<T> list1, List<T> list2) {&nbsp; &nbsp; int shorter = Math.min(list1.size(), list2.size());&nbsp; &nbsp; int longer = Math.max(list1.size(), list2.size());&nbsp; &nbsp; Stream<T> firstPart = IntStream.range(0, shorter).mapToObj(x -> Stream.of(list1.get(x), list2.get(x))).flatMap(x -> x);&nbsp; &nbsp; if (longer > shorter) {&nbsp; &nbsp; &nbsp; &nbsp; Stream<T> secondPart = (list1.size() > list2.size() ? list1 : list2).subList(shorter, longer).stream();&nbsp; &nbsp; &nbsp; &nbsp; return Stream.concat(firstPart, secondPart).collect(Collectors.toList());&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; return firstPart.collect(Collectors.toList());&nbsp; &nbsp; }}魔法发生在mapToObj和中flatMap。它将每个索引映射到两个列表元素的流,一个来自每个给定的列表。然后它用 . 压扁流的流flatMap。之后,如果两个列表的大小不同,它会获取较长列表的其余部分并将其连接到末尾。

胡子哥哥

一种方法可能是使用 anIntStream获取列表索引流,Optional根据列表是否包含此索引将它们映射到 s,然后解析它们,但老实说,我不确定这是否更优雅比你原来的方法:public <T> List<T> mixingList(List<T> list1, List<T> list2) {&nbsp; &nbsp; int maxSize = Math.max(list1.size(), list2.size());&nbsp; &nbsp; return IntStream.range(0, maxSize)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .mapToObj(i -> Stream.of(listIndexToOptional(list1, i),&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;listIndexToOptional(list2, i)))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .flatMap(Function.identity())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(Optional::isPresent)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(Optional::get)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());}private static <T> Optional<T> listIndexToOptional(List<T> list, int index) {&nbsp; &nbsp; return index < list.size() ? Optional.of(list.get(index)) : Optional.empty();}

暮色呼如

您可以将其分成两部分。首先,你得到两个列表的最小数量,然后混合两个列表直到这个索引。之后,您将剩余的项目附加到更大的列表中。要结合两者,您可以使用Stream.concat():private static <T> List<T> mixingList(List<T> list1, List<T> list2) {&nbsp; &nbsp; int min = Math.min(list1.size(), list2.size());&nbsp; &nbsp; return Stream.concat(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IntStream.range(0, min).boxed()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .flatMap(i -> Stream.of(list1.get(i), list2.get(i))),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (list1.size() < list2.size() ? list2 : list1).stream().skip(min)&nbsp; &nbsp; ).collect(Collectors.toList());}或者,您可以Stream.concat()在使用时使用Stream.flatMap():private static <T> List<T> mixingList(List<T> list1, List<T> list2) {&nbsp; &nbsp; return IntStream.range(0, Math.max(list1.size(), list2.size())).boxed()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .flatMap(i -> Stream.concat(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i < list1.size() ? Stream.of(list1.get(i)) : Stream.empty(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i < list2.size() ? Stream.of(list2.get(i)) : Stream.empty()))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());}
随时随地看视频慕课网APP

相关分类

Java
我要回答