java 集合学习笔记3-HashSet TreeSet

1、集合-HashSet:存储不重复的元素,没有索引
    底层主要是调用HashCode和Equals方法判断
    
    
    存储字符:
        HashSet<String> hs = new HashSet<>();
        boolean b1 = hs.add("a");
        boolean b2 = hs.add("a"); //当存储不成功的时候,返回false
        
        System.out.println(b1);
        System.out.println(b2);
        for(String s : hs) {
            System.out.println(s);  //输出[a]
        }
    
2、集合-HashSet存储自定义对象
    HashSet<Person> hs = new HashSet<>();
    hs.add(new Person("张三", 23));
    hs.add(new Person("张三", 23));
    hs.add(new Person("李四", 24));
    
    //System.out.println(hs.size());
    System.out.println(hs);  //实际上没有把重复的删除
    
    因为需要调用对象的HashCode和Equals的方法,但是Person类中没有重写
    
    
    例如:
        public class Person {
            private String name;
            private int age;
            public Person() {
                super();
                
            }
            public Person(String name, int age) {
                super();
                this.name = name;
                this.age = age;
            }
            public String getName() {
                return name;
            }


            public int getAge() {
                return age;
            }


            @Override
            public String toString() {
                return "Person [name=" + name + ", age=" + age + "]";
            }


            
            /*
             * 为什么是31?
             * 1,31是一个质数,质数是能被1和自己本身整除的数
             * 2,31这个数既不大也不小
             * 3,31这个数好算,2的五次方-1,2向左移动5位
             */
            @Override
            public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + age;
                result = prime * result + ((name == null) ? 0 : name.hashCode());
                return result;
            }
            //可以使用eclipse自动生成equals方法
            @Override
            public boolean equals(Object obj) {
                if (this == obj) //调用的对象和传入的对象是同一个对象
                    return true; //直接返回true
                if (obj == null) //传入的对象为null
                    return false; //返回false
                if (getClass() != obj.getClass()) //判断两个对象对应的字节码文件是否是同一个字节码
                    return false; //如果不是直接返回false
                Person other = (Person) obj; //向下转型
                if (age != other.age) //调用对象的年龄不等于传入对象的年龄
                    return false; //返回false
                if (name == null) { //调用对象的姓名为null
                    if (other.name != null) //传入对象的姓名不为null
                        return false; //返回false
                } else if (!name.equals(other.name)) //调用对象的姓名不等于传入对象的姓名
                    return false; //返回false
                return true; //返回true
            }
            
        }


3、集合-HashSet原理
    我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
如果没有哈希值相同的对象就直接存入集合
如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
    
    
    
4、集合-LinkedHashSet:可以保证怎么存就怎么取 
    底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
    
    LinkedHashSet<String> lhs = new LinkedHashSet<>();
lhs.add("a");
lhs.add("a");
lhs.add("a");
lhs.add("a");
lhs.add("b");
lhs.add("c");
lhs.add("d");

System.out.println(lhs);
        //输出的是[a,b,c,d]
    
    
    
    
5、集合-TreeSet:可以进行排序
    TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
    底层是根据compareTo()方法返回的结果进行存储
    
    如果需要排序自定义的类,就需要重写里面的compareTo方法
    
    例如:
        TreeSet<Integer> ts = new TreeSet<>();
        ts.add(3);
        ts.add(1);
        ts.add(1);
        ts.add(2);
        ts.add(2);
        ts.add(3);
        ts.add(3);
        System.out.println(ts);
        //返回的是[1,2,3]
    
6、集合-TreeSet原理:
    当compareTo方法返回0的时候集合中只有一个元素,就不存储
    当compareTo方法返回负数的时候集合会倒序存储,就存在树的左边
当compareTo方法返回正数的时候集合会怎么存就怎么取,就存在树的右边
    
    取数据的时候就从最左边开始取(从根开始,如果左边有数据就看这个数据的左边还有没有,依次类推,到了最左边就取出来)

    TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
TreeSet如果传入Comparator, 就优先按照Comparator
    例如:
        public static void main(String[] args) {
            //需求:将字符串按照长度排序
            TreeSet<String> ts = new TreeSet<>(new CompareByLen()); //Comparator c = new CompareByLen();
            ts.add("aaaaaaaa");
            ts.add("z");
            ts.add("wc");
            ts.add("nba");
            ts.add("cba");
            System.out.println(ts);
        }
    
        //定义一个比较器的类,实现Comparator接口
        class CompareByLen implements Comparator<String> {


            @Override
            public int compare(String s1, String s2) { //按照字符串的长度比较
                int num = s1.length() - s2.length(); //长度为主要条件
                return num == 0 ? s1.compareTo(s2) : num; //内容为次要条件,s1就是"z"需要比较的字符串(ts.add("z");),s2就是TreeSet里面的数据
            }                                               //==0就按默认的排序
        }
    

    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值