• java中set接口、哈希表、哈希值、HashSet、LinkedHashSet、方法的可变参数


    set接口:

    set接口和list接口一样,都是继承于Collection接口,它与Collection接口中的方法基本一致。特点:不允许存储重复元素,元素没有索引。它主要有两个实现类:HashSet(具有哈希表结构,实际是一个HashMap实例,它的没有顺序,但是查询速度非常快,底层也不是同步的 )和LinkedHashSet

    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    // set接口:继承于Collection接口,不允许存储重复元素,且没有索引,因此不能使用带索引的方法,也不能使用普通的for遍历
    // set接口主要有两个实现类:HashSet和
    // 1.HashSet特点:1.不允许存储重复元素 2.没有索引,不能使用带索引的方法,也不能使用普通的for遍历 3.无序的集合,存取元素的顺序可能不同 4.底层是一个哈希表结构(查询速度非常快)
    public class setInterfaceClass {
        public static void main(String[] args) {
            // 使用多态的方式创建一个HashSet集合:
            Set<Integer> st = new HashSet<Integer>();
            // 使用add方法向集合中添加元素:
            st.add(1);
            st.add(2);
            st.add(2);
            st.add(4);
            System.out.println(st); // [1, 2, 3, 4]
            // 遍历st集合:不能使用for遍历没有索引的集合:一般使用迭代器或增强for遍历没有索引的集合:
            // for (int i = 0; i < st.size();i++) {
            //    System.out.println(st[i]);
            //}
            Iterator<Integer> it = st.iterator();
            while (it.hasNext()) {
                int num = it.next();
                System.out.println(num); // 分别打印出了每个元素,但是2只打印了一次,因为存元素时不会存入重复的元素
            }
            for (int i : st) {
                System.out.println(i); // 分别打印出了每个元素,但是2只打印了一次,因为存元素时不会存入重复的元素
            };
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    哈希表:

    HashSet集合存储数据的结构就是使用哈希表,那么什么是哈希表?想要了解哈希表,那么就先了解哈希值。

    哈希值 :一个十进制的整数,由系统随机给出(实际就是对象的地址值,但是并非物理地址,而是模拟出来的地址,在Object类中有一个hashCode方法可以获取对象的哈希值),

    定义一个继承了Object的类:

    // 定义一个TestClass类并继承Object
    public class TestClass extends Object{
        // 点进Object查找hashCode方法可以看到源码:public native int hashCode(); 此方法没有方法体,而是有一个native,表示该方法调用了本地系统方法
    }
    
    • 1
    • 2
    • 3
    • 4

    使用TestClass类创建对象,并使用hashCode方法:

    // 哈希值:一个由系统随机给出的对象整数地址值,hashCod方法可以返回这个哈希值:
    public class hashCodeMethodsClass {
        public static void main(String[] args) {
            // 创建一个TestClass类的对象,又因为TestClass类继承了Object,因此可以调用hashCode方法:
            TestClass tc = new TestClass();
            int hashValue = tc.hashCode();
            System.out.println(hashValue); // 1967205423 ,每次执行都会得到不同的值
    
            TestClass tc2 = new TestClass();
            int hashValue2 = tc2.hashCode();
            System.out.println(hashValue2); // 42121758 ,每次执行都会得到不同的值
            System.out.println(tc == tc2); // false
     
            // 如何我们重写hashCode方法,那么返回值就一直是一个定值,虽然返回值的哈希值是相同的,但是这两个对象也是不相等的,因为物理地址不同
    
            // String类的哈希值:
            String s1 = new String("abc");
            String s2 = new String("abc");
            System.out.println(s1.hashCode()); // 96354
            System.out.println(s2.hashCode()); // 96354
            System.out.println(s1 == s2); // false
    
            // 字符串不相同,哈希值也是有可能相同的,如:
            System.out.println("重地".hashCode()); // 1179395
            System.out.println("通话".hashCode()); // 1179395
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    哈希表结构:

    jdk1.8之前哈希表 = 数组+链表,jdk1.8之后哈希表= 数组+ 红黑树(提高查询速度)
    在这里插入图片描述
    set集合不能存储重复元素的原理 :

    import java.util.HashSet;
    
    // set集合不允许存储重复元素的原理:
    public class setNoRepet {
        public static void main(String[] args) {
            HashSet<String> st = new HashSet<String>();
            String s1 = new String("abc");
            String s2 = new String("abc");
    
            st.add(s1);
            st.add(s2);
            st.add("重地");
            st.add("通话");
            st.add("abc");
    
            System.out.println(st); // [重地, 通话, abc] ,每次添加元素底层都会调用hashCode计算哈希值,并将这个哈希值水平存到数组中,如果有相同的哈希值元素被添加,那么会继续调用equals方法进一步比较两个元素是否相同,如果相同则不会存储,否则会在垂直方向将元素存到对应哈希值下面
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述
    HashSet存储自定义类型元素:

    给HashSet中存放自定义元素时,需要重写对象中hashCode和equals方法,建立自己的比较方法,才能保证HashSet集合中的对象唯一。

    自定义类:

    import java.util.Objects;
    
    public class Person {
        private String name;
        private int age;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Person() {
        }
    
        //  重写equals和hashCode方法代码可以alt+insert自定生成:
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Person person = (Person) o;
            return age == person.age && Objects.equals(name, person.name);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    使用HashSet存储自定义元素:

    import java.util.HashSet;
    
    // HashSet存储自定义元素:set集合存储元素唯一,以后如果要在HasHset中存储元素,一定要覆重写hashCode和equals方法:
    public class customElementSaveHashSet {
        public static void main(String[] args) {
            Person p1 = new Person("小明",12);
            Person p2 = new Person("小明",12);
            Person p3 = new Person("小红",22);
    
            HashSet<Person> ps = new HashSet<>();
            ps.add(p1);
            ps.add(p2);
            ps.add(p3);
            System.out.println(p1.hashCode()); //1967205423
            System.out.println(p2.hashCode()); //42121758
            System.out.println(p3.hashCode()); //20671747
            System.out.println(ps); // [Person@13b6d03, Person@282ba1e, Person@75412c2f], 存进去了两个对象
    
            // 上面是没有重写hashCode方法和equals方法,会存三个值进去,下面是重写了Person类中的hashCode和equals方法的结果:
            System.out.println(p1.hashCode()); //23458766
            System.out.println(p2.hashCode()); //23458766
            System.out.println(p3.hashCode()); //23653828
            System.out.println(ps); // [Person@165f3ce, Person@168edc4]
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    LinkedHashSet集合:

    LinkedHashSet是一个具有可预知迭代顺序set接口的哈希表和链表的实现,继承于HashSet集合,与hashSet不同之处在于LinkedHashSet维护着一个运行于所有条目的双重链接列表,此链接列表定义了迭代顺序(按照将元素插入到set中的顺序,且插入的顺序不受set中重新插入元素影响)

    import java.util.HashSet;
    import java.util.LinkedHashSet;
    
    // LinkedHashSet继承于HashSet集合,底层是一个哈希表(数组+链表/红黑树)和链表构成,可以看出是双链,其中一条是记录元素存储顺序的。
    public class LinkedHashSetClass {
        public static void main(String[] args) {
            // 创建一个HashSet集合:
            HashSet<String> st = new HashSet<>();
            st.add("WWW");
            st.add("abc");
            st.add("abc");
            st.add("hello");
            System.out.println(st); // [abc, WWW, hello] ,可以看到遍历的顺序和存储的顺序是不一致且不允许重复存储的。
    
            // 创建一个LinkedHashSet集合:
            LinkedHashSet<String> ls = new LinkedHashSet<>();
            ls.add("WWW");
            ls.add("abc");
            ls.add("abc");
            ls.add("hello");
            System.out.println(ls); // [WWW, abc, hello] ,可以看到与HashSet集合不一致的是:元素存储迭代是有顺序的,且也是不重复
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    可变参数:

    在jdk1.5之后,如果定义的方法需要接收多个参数,且参数数据类型一致,那么我们可以对其传入参数简化书写:(参数类型…形参名),当方法的参数类型确定而参数个数不确定时可以使用可变参数,可变参数实际是一个数组(传递几个参数就会创建一个存几个元素的数组 )将每个参数存起来了,如:

    public class VarParamClass {
        public static void main(String[] args) {
            getSum(); // 0
            getSum(2,4); // 2
        }
        // 一个方法的可变参数列表只能有一个参数,也就是说可变的参数只能有一个:
        public static void getSum(int...num) {
            System.out.println(num.length);
        };
    
        // 如果有多个参数,其中有一个可变参数,那么这个可变参数放到最后面试可行的:
        public static void getResult(String s,int n, Boolean b, int...num) {
            System.out.println(num.length);
        };
    
        // 当有多个参数时,可变参数不能放到其他位置,只能放到末尾:
        // public static void getReut(int...num,String s,int n, Boolean b) {
        //    System.out.println(num.length);
        //};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    提示:本文图片等素材来源于网络,若有侵权,请发邮件至邮箱:810665436@qq.com联系笔者删除。
    笔者:苦海

  • 相关阅读:
    python数据分析与挖掘实战————银行分控模型(几种算法模型的比较)
    从0开始学统计-什么是回归?
    Django后台忘记管理员的账号
    数据结构与算法(07)之数组与字符串解法(双指针,快慢指针,哈希表,KMP算法等)
    【开发经验】通知气泡实现思路
    遗传算法极限学习机GA-ELM回归预测及其MATLAB代码实现
    用array_filter清除数组中的空值
    KingbaseES参数track_activity_query_size介绍
    Vosviewer的安装与使用
    Vagrant的安装和使用(附带安装Centos 7教程)
  • 原文地址:https://blog.csdn.net/weixin_46758988/article/details/128154484