List 一定有序,Set不一定无序 ---AND--- 去除List集合中的重复值(6种好用的方法)----ANG--为什么Set会去重

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)); 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值