Set集合

概述

  • java.util.Set接口 extends Collection接口
  • Set接口的特点
       1) 不允许存储重复的元素
       2)没有索引,没有带索引的方法,也不能使用普通的for循环遍历;

HashSet集合

  • java.util.HashSet集合 implements Set接口
  • HashSet特点:
       1)不允许存储重复的元素
       2)没有索引,也没有带索引的方法,也不能使用普通的for循环遍历(可以使用迭代器和增强for循环遍历)
       3)是一个无序的集合,存储元素和取出元素的顺序有可能不一致;
       4)底层是一个哈希表结构(查询的速度非常快)

哈希值

  • 是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来的地址,不是数据实际存储的物理地址)
  • 在Object类有一个方法,可以获取对象的哈希值;
  • int hashCode():返回该对象的哈希码值;
    hashCode()的源码:public native int hashCode();
    native:代表该方法调用的是本地操作系统的方法
public class HashCode {
    public static void main(String[] args) {
        HashCode hc1=new HashCode();
        int h1=hc1.hashCode();
        System.out.println(h1);//460141958

        HashCode hc2=new HashCode();
        int h2=hc2.hashCode();
        System.out.println(h2);//1163157884

        /*
        toString()的源码:其实也是调用了hashcode()方法
             return getClass().getName() + "@" + Integer.toHexString(hashCode());
         */
        System.out.println(hc1.toString());//HashCode@1b6d3586(460141958的十六进制)
        System.out.println(hc2.toString());//HashCode@4554617c(1163157884的十六进制)

        /*
        String类的哈希值
           String类重写了Object类的hashCode()方法,直接返回十进制hash值
         */

        String s1=new String("abc");
        String s2=new String("bcd");
        System.out.println(s1.hashCode());//96354
        System.out.println(s2.hashCode());//97347

        System.out.println("重地".hashCode());//1179395
        System.out.println("通话".hashCode());//1179395
    }
}

哈希表结构

Set集合不允许存储重复元素的原理

不存储重复元素原理

HashSet存储自定义类型元素

  • 给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一 ;
//同名同年龄的人是同一个人
public class Person {
    private String name;
    private int age;

    public Person(String name,int age){
        this.age=age;
        this.name=name;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name,age);
    }

    @Override
    public boolean equals(Object obj) {
        if(this == obj)
            return true;
        if(obj == null || getClass() != obj.getClass())
            return false;
        //向下转型
        Person p=(Person)obj;
        return this.age==p.age && Objects.equals(this.name,p.name);
    }

    public static void main(String[] args) {
        //同名同年龄的人是同一个人,若不重写hashcode方法得到的是两个不同的hash值
        Person p1=new Person("gg",20);
        Person p2=new Person("gg",20);

        System.out.println(p1.hashCode());//103157
        System.out.println(p2.hashCode());//103157,哈希值相同
        System.out.println(p1.equals(p2));//true,内容相同
        System.out.println(p1.equals(p2));//重写了之后比较的是内容,而不是内存中的地址值
        System.out.println(p1 == p2);//false,p1在内存中的地址值和p2不一样(即使逻辑地址hash值一样)
    }

LinkedHashSet集合

  • java.util.LinkedHashSet集合 extens HashSet集合
  • 特点:
       1)底层是一个哈希表+链表:多了一条链表(记录元素的存储顺序),保证元素有序;
       2)有序,不重复

可变参数

  • 可变参数:是JDK1.5之后出现的新特性
  • 使用前提:当方法的参数列表数据类型已经确定,但是参数的个数不确定时,就可以使用可变参数
  • 使用格式:定义方法时使用
    修饰符 返回值类型 方法名(数据类型…变量名){}(注意:三个点)
  • 可变参数的原理
    可变参数的底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数;
  • 可变参数注意事项:
    1)一个方法的参数列表,只能有一个可变参数
    2)如果方法的参数有多个,那么可变参数必须写在参数列表的末尾;
public class KeBianCanShu {

    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3};
        add(arr);//一种方式传入数组
        add(10,20,30);//另一种方式,直接传入多个参数
    }
    //可变参数示例
    public static void add(int... arr){
        for(int i:arr)
            System.out.println(i);
    }
    //可变参数注意事项
    public static void method(int... arr,String... arrS){}//报错,一个方法的参数列表中只能有一个可变参数
    public static void method1(int... arr,String s,double d){};//报错,可变参数只能放在参数列表末尾
}

  • 可变参数的特殊(终极)写法
 public static void method2(Object... obj){}//可以接收任意类型的数据
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值