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

分组后对列表进行排序

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

分组后对列表进行排序

在操作

sorted(comparator)
之前在流上
collect
使用时,流必须缓冲整个流内容才能对其进行排序,与之后对组的较小列表进行排序相比,排序可能涉及该缓冲区内更多的数据移动。因此,如果启用了并行处理,则实现将利用多个内核,因此性能不如对各个组进行排序。

但是请注意,using

sortedListsByGender.values().forEach(…)
不是可并行化的操作,即使using
sortedListsByGender.values().parallelStream().forEach(…)
只能允许并行处理组,而每个排序操作仍是顺序的。

当在收集器中执行排序操作时,如下所示

static <T> Collector<T,?,List<T>> toSortedList(Comparator<? super T> c) {    return Collectors.collectingAndThen(        Collectors.toCollection(ArrayList::new), l->{ l.sort(c); return l; } );}Map<Gender, List<Person>> sortedListsByGender = roster.stream()    .collect(Collectors.groupingBy(Person::getGender, toSortedList(Person::compareByAge)));

排序操作的行为相同(感谢Tagir Valeev纠正了我),但是您可以轻松地检查插入排序策略的执行情况。只需将收集器实现更改为:

static <T> Collector<T,?,List<T>> toSortedList(Comparator<? super T> c) {    return Collectors.collectingAndThen(        Collectors.toCollection(()->new TreeSet<>(c)), ArrayList::new);}

为了完整起见,如果您想要一个收集器,该收集器首先将一个插入到的

ArrayList
中,以避免最后的复制步骤,则可以使用更复杂的收集器,如下所示:

static <T> Collector<T,?,List<T>> toSortedList(Comparator<? super T> c) {    return Collector.of(ArrayList::new,        (l,t) -> { int ix=Collections.binarySearch(l, t, c); l.add(ix<0? ~ix: ix, t);        },        (list1,list2) -> { final int s1=list1.size(); if(list1.isEmpty()) return list2; if(!list2.isEmpty()) {     list1.addAll(list2);     if(c.compare(list1.get(s1-1), list2.get(0))>0)         list1.sort(c); } return list1;        });}

它对于顺序使用是有效的,但是其合并功能并不是最佳的。底层的排序算法将受益于预排序的范围,但是尽管我们的合并功能实际上知道这些范围,但必须首先找到这些范围。不幸的是,JRE中没有公共API允许我们利用这些信息(有效;我们可以将传递

subList
给,
binarySearch
但是为的每个元素创建一个新的子列表
list2
可能会变得太昂贵)。如果要进一步提高并行执行的性能,则必须重新实现排序算法的合并部分:

static <T> Collector<T,?,List<T>> toSortedList(Comparator<? super T> c) {    return Collector.of(ArrayList::new,        (l,t) -> l.add(insertPos(l, 0, l.size(), t, c), t),        (list1,list2) -> merge(list1, list2, c));}static <T> List<T> merge(List<T> list1, List<T> list2, Comparator<? super T> c) {    if(list1.isEmpty()) return list2;    for(int ix1=0, ix2=0, num1=list1.size(), num2=list2.size(); ix2<num2; ix2++, num1++) {        final T element = list2.get(ix2);        ix1=insertPos(list1, ix1, num1, element, c);        list1.add(ix1, element);        if(ix1==num1) { while(++ix2<num2) list1.add(list2.get(ix2)); return list1;        }    }    return list1;}static <T> int insertPos(    List<? extends T> list, int low, int high, T t, Comparator<? super T> c) {    high--;    while(low <= high) {        int mid = (low+high)>>>1, cmp = c.compare(list.get(mid), t);        if(cmp < 0) low = mid + 1;        else if(cmp > 0) high = mid - 1;        else { mid++; while(mid<=high && c.compare(list.get(mid), t)==0) mid++; return mid;        }    }    return low;}

注意,与

binarySearch
基于简单的插入不同,最后一种解决方案是一种稳定的排序实现,即,在您的情况下,
Person
s具有相同的年龄并且
Gender
如果源流具有定义的遇到顺序,则不会更改其相对顺序。



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

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

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