簡體   English   中英

使用流交替混合兩個列表

[英]Mixing two lists alternately using stream

我使用循環實現了這個,但我不知道如何使用流。 我們得到兩個列表,例如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流上做到這一點?

以下是使用流的解決方案:

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());
    }
}

魔術發生在mapToObjflatMap 它將每個索引映射到兩個列表元素的流,每個列表元素中給出一個列表元素。 然后用flatMap平坦化流的流。

之后,如果兩個列表具有不同的大小,它將獲取較長列表的其余部分並將其連接到末尾。

一種方法可能是使用IntStream獲取列表索引流,根據列表是否包含此索引將它們映射到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();
}

您可以將其拆分為兩部分。 首先,您獲得兩個列表的最小數量,並將兩個列表混合到此索引。 之后,您將其余項目附加到較大的列表中。 要將兩者結合使用,您可以使用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());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM