HashSet集合介绍:
/*
* java.util.Set接口 extends Collection接口
* Set接口的特点:
* 1.不允许存储重复的元素
* 2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
* java.util.HashSet集合,implements Set接口
* HashSet特点:
* 1.不允许存储重复的元素
2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致。
4.底层是一个哈希表结构(查询的速度非常快)
*/
public class Demo01Set {
public static void main(String[] args) {
Set<Integer> set=new HashSet<>();
//使用add方法往集合中添加元素
set.add(1);
set.add(3);
set.add(2);
set.add(4);
set.add(1);
//使用迭代器遍历Set集合
Iterator<Integer> it = set.iterator();
while(it.hasNext()){
Integer n=it.next();
System.out.println(n);//1,2,3,4
}
//使用增强for遍历
System.out.println("---------");
for (Integer i : set) {
System.out.println(i);
}
}
}
哈希值:
/*
* 哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址)
* 在Object类有一个方法,可以获取对象的哈希值
* int hashCode()返回对象的哈希码值。
* hashCode()方法的源码:
* public native int hashCode();
* native:代表该方法调用的是本地操作系统的方法。
* */
public class Demo02HashCode {
public static void main(String[] args) {
//Person类继承了Object类,所以可以使用Object类的hashCode方法。
Person p1=new Person();
int h1 = p1.hashCode();
System.out.println(h1);
Person p2=new Person();
int h2 = p2.hashCode();
System.out.println(h2);
/*
* toString方法的源码:
* return getClass().getName() + "@" + Integer.toHexString(hashCode());
* */
System.out.println(p1);
System.out.println(p2);
/*
* String类的哈希值:
* String类重写Object类的hashCode方法
* */
String s1=new String("abc");
String s2=new String("abc");
System.out.println(s1.hashCode());//96354
System.out.println(s2.hashCode());//96354
}
}
HashSet集合存储数据的结构(哈希表):
哈希表=数组+链表;
哈希表=数组+红黑树(提高查询的速度)。
哈希表的特点:查询的速度快。
数组结构:把元素进行了分组(相同哈希值的数组是一组),链表/红黑树把相同哈希值的元素连接到一起
存储数据到集合中
先计算元素的哈希值
两个元素不同,但哈希值相同,称为哈希冲突
如果链表的长度超过了8位
那么就会把链表转换为红黑树(提高查询的速度)。
Set集合存储元素不重复的原理:
Set集合在调用add方法的时候,add方法会调用元素的hashCode方法和equals方法,判断元素是否重复。
发生哈希冲突时,进行相同哈希值的元素进行比较,若相同,则不进行存储;若不同,就存储到集合中。
HashSet集合存储自定义类型元素:
/* * HashSet存储自定义类型元素: * set集合报错元素唯一: * 存储的元素(String、Integer、...Student、Person...),必须重写hashCode和equals方法 * 要求: * 同名和同年龄的人,视为同一个人,只能存储一次。 * */ public class Demo01HashSetSavePerson { public static void main(String[] args) { //创建HashSet集合存储Person HashSet<Person> set=new HashSet<>(); Person p1=new Person("小美女",18); Person p2=new Person("小美女",18); Person p3=new Person("小美女",19); //重写hashCode和equals方法后 System.out.println(p1.hashCode());//1355531311 734175839 System.out.println(p2.hashCode());//1967205423 734175839 System.out.println(p1==p2);//false false System.out.println(p1.equals(p2));//false true set.add(p1); set.add(p2); set.add(p3); System.out.println(set); } }
LinkedHashS集合:
/* * java.util.LinkedHashSet集合 extends HashSet集合 * LinkedHashSet集合特点: * 底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序 * */ public class Demo02LinkedHashSet { public static void main(String[] args) { HashSet<String> set=new HashSet<>(); set.add("abc"); set.add("abc"); set.add("hello"); set.add("world"); System.out.println(set);//[abc, world, hello]无序,且不允许重复 LinkedHashSet<String> set1=new LinkedHashSet<>(); set1.add("abc"); set1.add("abc"); set1.add("hello"); set1.add("world"); System.out.println(set1);//[abc, hello, world]有序,不允许重复 } }
可变参数:
/* * 可变参数:jdk1.5之后出现的新特性 * 使用前提: * 当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数。 * 使用格式: * 修饰符 返回值类型 方法名(数据类型...变量名){} * 可变参数原理: * 可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数 * 传递的参数个数,可以是0个(不传递),1,2...多个*/ public class Demo02VarArgs { public static void main(String[] args) { int i=add(10,20,30,40,50,60); System.out.println(i);//210 } /* * 可变参数的注意事项: * 1.一个方法的参数列表,只能有一个可变参数 * 2.如果方法的参数有多个,那么可变参数必须写在参数列表的末尾 * */ //可变参数的特殊(终极)写法 public static void method(Object...obj){ } /* * 定义计算(0-n)整数和的方法: * 已知:计算整数的和,数据类型已经确定int * 但是参数的个数不确定,不知道计算几个整数的和,就可以使用可变参数 * add();就会创建一个长度为0的数组,new int[0] * add(10);就会创建一个长度为1的数组,存储传递过来的参数 new int[]{10}; * add(10,20);就会创建一个长度为2的数组,存储传递过来的参数 new int[]{10,20}; * add(10,20,30,40,50,60);就会创建一个长度为6的数组,存储传递过来的参数 new int[]{10,20,30,40,50,60}; * */ public static int add(int...arr){ //System.out.println(arr);//[I@1c53fd30 底层是一个数组 //System.out.println(arr.length);//0,1,2,6 //定义一个初始化的变量,记录累加求和 int sum=0; //遍历数组,获取数组中的每一个元素 for (int i : arr) { //累加求和 sum +=i; } //把求和结果返回 return sum; } /*//定义一个方法,计算三个整数的和 public static int add(int a,int b,int c){ return a+b+c; } //定义一个方法,计算两个整数的和 public static int add(int a,int b){ return a+b; }*/ }