子列表上的分区列表,其中邻居子列表的第一个元素和最后一个元素相同

时间:2018-08-14 17:07:50

标签: java list split element overlap

有对象列表:

[Object1, Object2, Object3, Object4, Object5]

应拆分为以下结构:

[
    [Object1, Object2, Object3]
    [Object3, Object4, Object5]
]

此代码可以拆分,而子列表的最后一个元素不重叠:

Streams.stream(Iterables.partition(maps,3)).collect(Collectors.toList());

结果是:

   [Object1, Object2, Object3]
   [Object4, Object5]

Object3 在这里缺失。

是否有一种优雅的方法来拆分此List,并重复将上一个子列表的
最后一个元素作为下一个子列表的第一个元素?

我已经尝试过这种方法,但是看起来并不像我希望的那么优雅:

List<List<String>> res= new ArrayList<>();
for (int y = 0; y < input.size() - 1;) {
    List<String> sub = paths.subList(y, y += 3);
    res.add(sub)
    --y;
}

3 个答案:

答案 0 :(得分:4)

带有流的解决方案,其中Intstream.iterate()具有以下签名,仅带有2个参数:

IntStream iterate(int seed, IntUnaryOperator f)

如下:

List res = IntStream.iterate(0, i -> i + step - 1)
        .limit(input.size() / (step - 1))
        .mapToObj(i -> input.subList(i, Math.min(i + step, input.size())))
        .collect(Collectors.toList());

step大小为3,输出:

[[a, b, c]]             //List<String> input = Arrays.asList("a","b","c");
[[a, b, c], [c, d]]     //List<String> input = Arrays.asList("a","b","c","d");

答案 1 :(得分:3)

就我个人而言,我将使用当前循环的一种变体,但将增量移至循环头。另请注意,您的代码仅在列表完全可分割时才有效,因此在我的版本中为Math.min

public static <T> List<List<T>> split(List<T> input, int k) {
    List<List<T>> res= new ArrayList<>();
    for (int i = 0; i < input.size() - 1; i += k-1) {
        res.add(input.subList(i, Math.min(input.size(), i + k)));
    }
    return res;
}

或者,如果您更喜欢Streams,则可以使用IntStream.iterate 1

public static <T> List<List<T>> split(List<T> input, int k) {
    return IntStream.iterate(0, i -> i < input.size(), i -> i + k-1)
            .mapToObj(i -> input.subList(i, Math.min(input.size(), i + k)))
            .collect(Collectors.toList());
}

示例,对于两个版本:

List<Integer> input = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
System.out.println(split(input, 3));
// [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]]

1)注意:Java 9+中提供了三参数版本。有关Java 8,请参见Pankaj's answer

答案 2 :(得分:0)

有很多方法可以做到这一点,其中一种是优雅的方法。

public class SplitList {

    public static <T> List<List<T>> split(List<T> list) {
        if (list == null || list.isEmpty()) {
            throw new RuntimeException("List shouldn't be empty");
        }

        int[] positions = {0, (list.size() + 1) / 2, list.size()};

        boolean isListOdd = list.size() % 2 != 0;

        return IntStream.rangeClosed(0, 1)
                .mapToObj(i -> list.subList(positions[i] + (isListOdd ? (i != 0 ? -1 : 0) : 0), positions[i + 1]))
                .collect(Collectors.toList());
    }

    public static void main(String[] args) {
        List<String> list = Arrays.asList("A", "B", "C", "D", "E");
        System.out.println(split(list));
    }
}

这是输出

[[A, B, C], [C, D, E]]