0、
Set之所以会去重,和map有很大的关系。
看源码你会发现HashSet底层使用HashMap存储
TreeSet底层使用TreeMap存储
LinkedHashSet底层使用LinkedHashMap存储
拿HashSet为例子,我们查看add()方法的源码
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
return的map对象其实是 一个HashMap
private transient HashMap<E,Object> map;1
再看map.put(e, PRESENT)
被传进来的泛型对象当成了Map的键,因为Map键值重复的话新的键会覆盖旧的键值,所以Set不会重复。
1、我们经常听说List是有序且重复的, Set 是无序不重复的。这里有个误区,这里说的顺序有两个概念,一是按添加的顺序排列,二是按自然顺序 a-z 排列。 Set 并不是无序的,传统说的
Set 无序是指 HashSet, 它不能保证元素的添加顺序,更不能保证自然顺序,而 Set 的其他实现类是可以实现这两种顺序的。
先来看看一段测试代码:
public class CollectionTest {
public static void main(String[] args) {
List<String> arrayList = new ArrayList<String>();
arrayList.add("s1");
arrayList.add("s3");
arrayList.add("s4");
arrayList.add("s5");
arrayList.add("s2");
System.out.println("ArrayList:==========================");
for(String arrList : arrayList){
System.out.println(arrList);
}
List<String> linkedList = new LinkedList<String>();
linkedList.add("s1");
linkedList.add("s3");
linkedList.add("s4");
linkedList.add("s5");
linkedList.add("s2");
System.out.println("LinkedList:===========================");
for(String linkList : linkedList){
System.out.println(linkList);
}
Set<String> hashSet = new HashSet<String>();
hashSet.add("s1");
hashSet.add("s3");
hashSet.add("s4");
hashSet.add("s5");
hashSet.add("s2");
System.out.println("HashSet:==============================");
for(String hashst: hashSet){
System.out.println(hashst);
}
Set<String> linkedHashSet = new LinkedHashSet<String>();
linkedHashSet.add("s1");
linkedHashSet.add("s3");
linkedHashSet.add("s4");
linkedHashSet.add("s5");
linkedHashSet.add("s2");
System.out.println("LinkedHashSet:=========================");
for(String linkedst : linkedHashSet){
System.out.println(linkedst);
}
Set<String> treeSet = new TreeSet<String>();
treeSet.add("s1");
treeSet.add("s3");
treeSet.add("s4");
treeSet.add("s5");
treeSet.add("s2");
System.out.println("TreeSet:==============================");
for(String treest : treeSet){
System.out.println(treest);
}
}
下面输出的结果:
ArrayList:==========================
s1
s3
s4
s5
s2
LinkedList:===========================
s1
s3
s4
s5
s2
HashSet:==============================
s3
s4
s5
s1
s2
LinkedHashSet:=========================
s1
s3
s4
s5
s2
TreeSet:==============================
s1
s2
s3
s4
s5
怎么样看出来了吧,我们通常说的 List 是you序的指的就是最后集合中的元素顺序就是按照添加时候的顺序排列的(无论是实现类 ArrayList, 还是 LinkedList)。但是我们发现 Set 所谓的无序就是在 HashSet 这个实现类中才会出现的这种情况,而 LinkedHashSet 已经和 List 的结果相同了,再看 TreeSet 实现的功能是根据元素的自然顺序排列了
作者:巧克力er
链接:https://www.jianshu.com/p/6f0da4dfcb09
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
2、最近项目中需要对list集合中的重复值进行处理,大部分是采用两种方法,一种是用遍历list集合判断后赋给另一个list集合,一种是用赋给set集合再返回给list集合。
但是赋给set集合后,由于set集合是无序的,原先的顺序就打乱了。所以我又想着能不能用set的特性进行去重又不打乱顺序呢?
试了一下,也是可以的,几种方法在不同情况下都有各自的优势。现在将代码写出来,比较一下。
//set集合去重,不打乱顺序
public static void main(String[] args){
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("aaa");
list.add("aba");
list.add("aaa");
Set set = new HashSet();
List newList = new ArrayList();
for (String cd:list) {
if(set.add(cd)){
newList.add(cd);
}
}
System.out.println( "去重后的集合: " + newList);
}
//遍历后判断赋给另一个list集合
public static void main(String[] args){
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("aaa");
list.add("aba");
list.add("aaa");
List<String> newList = new ArrayList<String>();
for (String cd:list) {
if(!newList.contains(cd)){
newList.add(cd);
}
}
System.out.println( "去重后的集合: " + newList);
}
//set去重
public static void main(String[] args){
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("aaa");
list.add("aba");
list.add("aaa");
Set set = new HashSet();
List newList = new ArrayList();
set.addAll(list);
newList.addAll(set);
System.out.println( "去重后的集合: " + newList);
}
//set去重(缩减为一行)
public static void main(String[] args){
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("aaa");
list.add("aba");
list.add("aaa");
List newList = new ArrayList(new HashSet(list));
System.out.println( "去重后的集合: " + newList);
}
hashset不进行排序,还有一种方法是用treeset,去重并且按照自然顺序排列,将hashset改为treeset就可以了。(原本的顺序是改变的,只是按照字母表顺序排列而已)
//去重并且按照自然顺序排列
List newList = new ArrayList(new TreeSet(list));