为了账号安全,请及时绑定邮箱和手机立即绑定

使用流交替混合两个列表

使用流交替混合两个列表

蓝山帝景 2023-03-23 16:35:50
我使用循环实现了这个,但我不知道如何使用流来实现。我们得到两个列表,例如 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 个测试 - 第二个列表大小相同 - 第三个是一个空列表 - 大小不同@Testpublic 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);}@Testpublic 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);}@Testpublic 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 流上做到这一点吗?
查看完整描述

3 回答

?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

这是使用流的解决方案:


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

    int shorter = Math.min(list1.size(), list2.size());

    int longer = Math.max(list1.size(), list2.size());

    Stream<T> firstPart = IntStream.range(0, shorter).mapToObj(x -> Stream.of(list1.get(x), list2.get(x))).flatMap(x -> x);

    if (longer > shorter) {

        Stream<T> secondPart = (list1.size() > list2.size() ? list1 : list2).subList(shorter, longer).stream();

        return Stream.concat(firstPart, secondPart).collect(Collectors.toList());

    } else {

        return firstPart.collect(Collectors.toList());

    }

}

魔法发生在mapToObj和中flatMap。它将每个索引映射到两个列表元素的流,一个来自每个给定的列表。然后它用 . 压扁流的流flatMap。


之后,如果两个列表的大小不同,它会获取较长列表的其余部分并将其连接到末尾。


查看完整回答
反对 回复 2023-03-23
?
胡子哥哥

TA贡献1825条经验 获得超6个赞

一种方法可能是使用 anIntStream获取列表索引流,Optional根据列表是否包含此索引将它们映射到 s,然后解析它们,但老实说,我不确定这是否更优雅比你原来的方法:


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

    int maxSize = Math.max(list1.size(), list2.size());


    return IntStream.range(0, maxSize)

            .mapToObj(i -> Stream.of(listIndexToOptional(list1, i), 

                                     listIndexToOptional(list2, i)))

            .flatMap(Function.identity())

            .filter(Optional::isPresent)

            .map(Optional::get)

            .collect(Collectors.toList());

}


private static <T> Optional<T> listIndexToOptional(List<T> list, int index) {

    return index < list.size() ? Optional.of(list.get(index)) : Optional.empty();

}


查看完整回答
反对 回复 2023-03-23
?
暮色呼如

TA贡献1853条经验 获得超9个赞

您可以将其分成两部分。首先,你得到两个列表的最小数量,然后混合两个列表直到这个索引。之后,您将剩余的项目附加到更大的列表中。要结合两者,您可以使用Stream.concat():


private static <T> List<T> mixingList(List<T> list1, List<T> list2) {

    int min = Math.min(list1.size(), list2.size());

    return Stream.concat(

            IntStream.range(0, min).boxed()

                    .flatMap(i -> Stream.of(list1.get(i), list2.get(i))),

            (list1.size() < list2.size() ? list2 : list1).stream().skip(min)

    ).collect(Collectors.toList());

}

或者,您可以Stream.concat()在使用时使用Stream.flatMap():


private static <T> List<T> mixingList(List<T> list1, List<T> list2) {

    return IntStream.range(0, Math.max(list1.size(), list2.size())).boxed()

            .flatMap(i -> Stream.concat(

                    i < list1.size() ? Stream.of(list1.get(i)) : Stream.empty(),

                    i < list2.size() ? Stream.of(list2.get(i)) : Stream.empty()))

            .collect(Collectors.toList());

}


查看完整回答
反对 回复 2023-03-23
  • 3 回答
  • 0 关注
  • 157 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信