栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

将列表沿元素拆分为子列表

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

将列表沿元素拆分为子列表

我目前想出的唯一解决方案是实现自己的自定义收集器。

在阅读解决方案之前,我想添加一些有关此的注释。我将这个问题更多地当作编程练习,我不确定是否可以使用并行流来完成。

因此,您必须意识到,如果 并行* 运行管道,它将 无声地中断*

不是 理想的行为,应该 避免 。这就是为什么我在组合器部分(而不是

(l1, l2) -> {l1.addAll(l2); returnl1;}
)中引发异常,因为在组合两个列表时会并行使用它,以便您有一个异常而不是错误的结果。

同样,由于列表复制,这种方法也不是很有效(尽管它使用本机方法来复制基础数组)。

因此,这是收集器的实现:

private static Collector<String, List<List<String>>, List<List<String>>> splitBySeparator(Predicate<String> sep) {    final List<String> current = new ArrayList<>();    return Collector.of(() -> new ArrayList<List<String>>(),        (l, elem) -> { if (sep.test(elem)) {     l.add(new ArrayList<>(current));     current.clear(); } else {     current.add(elem); }        },        (l1, l2) -> { throw new RuntimeException("Should not run this in parallel");        },        l -> { if (current.size() != 0) {     l.add(current);     return l; }        );}

以及如何使用它:

List<List<String>> ll = list.stream().collect(splitBySeparator(Objects::isNull));

输出:

[[a, b], [c], [d, e]]

当JoopEggen的答案出炉时,看来可以并行完成(为此感谢他!)。这样,它将自定义收集器实现简化为:

private static Collector<String, List<List<String>>, List<List<String>>> splitBySeparator(Predicate<String> sep) {    return Collector.of(() -> new ArrayList<List<String>>(Arrays.asList(new ArrayList<>())),  (l, elem) -> {if(sep.test(elem)){l.add(new ArrayList<>());} else l.get(l.size()-1).add(elem);},  (l1, l2) -> {l1.get(l1.size() - 1).addAll(l2.remove(0)); l1.addAll(l2); return l1;});}

这使有关并行性的段落过时了,但是我将其保留下来,因为它可以很好地提醒您。


请注意,Stream API并不总是可以替代。有些任务使用流更容易且更适合,有些则不是。对于您的情况,您还可以为此创建一个实用程序方法:

private static <T> List<List<T>> splitBySeparator(List<T> list, Predicate<? super T> predicate) {    final List<List<T>> finalList = new ArrayList<>();    int fromIndex = 0;    int toIndex = 0;    for(T elem : list) {        if(predicate.test(elem)) { finalList.add(list.subList(fromIndex, toIndex)); fromIndex = toIndex + 1;        }        toIndex++;    }    if(fromIndex != toIndex) {        finalList.add(list.subList(fromIndex, toIndex));    }    return finalList;}

并称它为

List<List<String>> list = splitBySeparator(originalList,Objects::isNull);

可以改进以检查边缘情况。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/449658.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号