我使用循环来实现这一点,但是我不知道如何使用流来实现。我们得到两个列表,例如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流上怎么做?
答案 0 :(得分:0)
这是使用流的解决方案:
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
使流的流变平坦。
此后,如果两个列表的大小不同,它将获取较长列表的其余部分并将其连接到末尾。
答案 1 :(得分:0)
一种方法可能是使用IntStream
获取列表索引流,根据列表是否包含该索引将它们映射到Optional
,然后解析它们,尽管,老实说,我不确定这是否比您的原始方法还要优雅:
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();
}
答案 2 :(得分:0)
您可以将其分为两部分。首先,您要获得两个列表的最小值,然后将两个列表混合在一起,直到获得该索引。之后,将其余项目追加到较大的列表中。要将两者结合使用,可以使用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());
}