Set排序⽅法
在讲解Set集合排序的⼏种⽅法之前,我们应该先清楚Set集合的⼏种类型以及特点,才能有效使⽤起来。
Set集合的特点
Set不允许包含相同的元素,如果试图把两个相同元素加⼊同⼀个集合中,add⽅法返回false。
Set判断两个对象相同不是使⽤==运算符,⽽是根据equals⽅法。也就是说,只要两个对象⽤equals⽅法⽐较返回true,Set就不会同时接受这两个对象。
Set集合的分类
Set集合主要分为3种:
|——SortedSet接⼝——TreeSet实现类
Set接⼝——|——HashSet实现类
|——LinkedHashSet实现类
HashSet(⽆序,可null)
HashSet的特点是不能保证元素的排列顺序,顺序有可能发⽣变化,集合元素可以是null,但只能放⼊⼀个null。因为在HashSet中存⼊⼀个元素的时候,会调⽤该对象的hashCode()⽅法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置,所以储存位置是随机的。HashSet就好像是HashMap的key。
TreeSet(有元素顺序的)
TreeSet是SortedSet接⼝的唯⼀实现类,TreeSet可以确保集合元素处于排序状态。TreeSet⽀持两种排序⽅式,⾃然排序 和定制排序,其中⾃然排序为默认的排序⽅式。⼀般的Set排序都会使⽤到TreeSet。
LinkedHashSet(记录插⼊顺序)
LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使⽤链表维护元素的次序。这样使得元素看起 来像是以插⼊顺 序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。⼀般的,如果让你设计⼀个缓存算法,LinkedHashSet就是基本的基础,利⽤LRU,筛选出应该淘汰的元素。
由于TreeSet是有元素顺序的,因此我们在排序的过程中都会使⽤TreeSet。
⽅法⼀:传统⽅法
public class TraditionalSetSortTest {
public static void main(String[] args){
Set<BigDecimal> set =new HashSet<>();
set.add(new BigDecimal(1.2).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(2.3).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(3.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(2.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(0.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(9.4).setScale(2, BigDecimal.ROUND_HALF_UP));
TreeSet<BigDecimal> sortSet =new TreeSet<>(new Comparator<BigDecimal>(){
@Override
public int compare(BigDecimal o1, BigDecimal o2){
return o1pareTo(o2);
}
});
sortSet.addAll(set);
System.out.println(sortSet);
}
}
--------------------------------------------------------------------------------------------
结果:[0.40,1.20,2.30,2.40,3.40,9.40]
⽅法⼆:lambda表达式
public class LambdaSetSortTest {
public static void main(String[] args){
Set<BigDecimal> set =new HashSet<>();
set.add(new BigDecimal(1.2).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(2.3).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(3.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(2.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(0.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(9.4).setScale(2, BigDecimal.ROUND_HALF_UP));
TreeSet<BigDecimal> sortedSet =new TreeSet<>(((o1, o2)-> o1pareTo(o2)));
sortedSet.addAll(set);
System.out.println(sortedSet);
}
}
--------------------------------------------------------------------------------------------
结果:[0.40,1.20,2.30,2.40,3.40,9.40]
⽅法三:使⽤Comparator,在jdk1.8以后,Comparator有Comparator.naturalOrder()⾃然排序这个⽅法,也有verseOrder()相反排序的⽅法。
public class ComparatorSetSortTest {
public static void main(String[] args){
Set<BigDecimal> set =new HashSet<>();
set.add(new BigDecimal(1.2).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(2.3).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(3.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(2.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(0.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(9.4).setScale(2, BigDecimal.ROUND_HALF_UP));
TreeSet<BigDecimal> sortedSet =new TreeSet<>(Comparator.naturalOrder());
sortedSet.addAll(set);
System.out.println(sortedSet);
}
}
-
-------------------------------------------------------------------------------------------
结果:[0.40,1.20,2.30,2.40,3.40,9.40]
⽅法四:使⽤Stream
这⾥使⽤Stream的时候可以转还成Set或者List,转换成Set的时候还需要再创建TreeSet,如果没有必须要求是Set,其实可以是直接转换成List,直接就是有序的,更加⽅便。
List list = set.stream().sorted(Comparator.naturalOrder()).List());
public class StreamSetSortTest {
public static void main(String[] args){
Set<BigDecimal> set =new HashSet<>();
bigdecimal取值范围set.add(new BigDecimal(1.2).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(2.3).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(3.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(2.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(0.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(9.4).setScale(2, BigDecimal.ROUND_HALF_UP));
Set newSet = set.stream().sorted(Comparator.naturalOrder()).Set());
TreeSet<Object> treeSet =new TreeSet<>();
treeSet.addAll(newSet);
System.out.println(treeSet);
}
}
--------------------------------------------------------------------------------------------
结果:[0.40,1.20,2.30,2.40,3.40,9.40]
补充:
已知数值a,如果要求向上取值(即寻顺序的Set集合中⼀个⼤于等于a的第⼀个元素,⽇常业务还是⽤到很多的,不到半⽄算半⽄(含),超过半⽄算⼀⽄类似),可以借⽤set的floor⽅法,数值超出元素的最⼤值后会返回null。
如果是BigDecimal类型,TreeSet集合元素与ceiling参数的⼩数点位数请务必保持⼀致。举例如下:
public class SetFloorMethod {
public static void main(String[] args){
Set<BigDecimal> set =new HashSet<>();
set.add(new BigDecimal(1.2).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(2.3).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(3.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(2.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(0.4).setScale(2, BigDecimal.ROUND_HALF_UP));
set.add(new BigDecimal(9.4).setScale(2, BigDecimal.ROUND_HALF_UP));
TreeSet<BigDecimal> sortedSet =new TreeSet<>(Comparator.naturalOrder());
sortedSet.addAll(set);
System.out.println(sortedSet);
BigDecimal value1 = iling(new BigDecimal(0.5).setScale(2, BigDecimal.ROUND_HALF_UP));
System.out.println("根据0.5可以取到元素:"+ value1);
BigDecimal value2 = iling(new BigDecimal(2.35).setScale(2, BigDecimal.ROUND_HALF_UP));
System.out.println("根据2.35可以取到元素:"+ value2);
BigDecimal value3 = iling(new BigDecimal(11).setScale(2, BigDecimal.ROUND_HALF_
UP));
System.out.println("根据11可以取到元素:"+ value3);
}
}
--------------------------------------------------------------------------------------------
结果如下:
[0.40,1.20,2.30,2.40,3.40,9.40]
根据0.5可以取到元素:1.20
根据2.35可以取到元素:2.40
根据11可以取到元素:null

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。