集合Collection是一个接口,它定义的是所有单列集合中共性的方法,所有单列集合都可以使用共性的方法,没有带索引的方法。
Collection有两个子类接口List、Set。
Set接口特点:
1.不允许存储重复元素
2.没有有索引,不能使用普通的for循环遍历
List有三个具体实现类:
TreeSet集合 HashSet集合 LinkedHashSet集合(其中LinkedHashSet是有序的
其中HashSet集合的特点为:
1.不允许存储重复元素
2.没有有索引,不能使用普通的for循环遍历
3.是一个无序的集合,存储元素和取出元素的顺序可能不一致
4.底层是一个哈希表结构(查询速度很快)
哈希表的底层构成在java 1.8以前是 数组+链表 的形式,java 1.8之后变为了 数组+链表+红黑树 当一个链表的长度大于8时,就会把链表变为红黑树的形式。
哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,而非数据存储的物理地址。)
Object类中有一个方法获得哈希值
int hashCode()返回该对象的哈希值
hashCode()方法的原码:
public native int hashCode()
native:代表该方法调用的是本地操作系统的方法。
Object的toString()方法返回的就是哈希值。另:特殊:“重地”、"通话"的哈希值相同,哈希冲突。
HashSet存储数据的原理(重复数据无法存储):
新建长度为16的数组用于存储哈希值,新添加的元素会把哈希值存入到数组中,哈希值相同的不同元素会以链表的形式排列,当再次添加元素时,会先调用 重写的 hashCode()方法判断数组中是否存在,在调用 重写的 equals()方法(否则比较地址值)判断元素是否相同。
HashSet存储自定义的类型元素:
要求:需要对自定义类型元素重写hashCode()和 equals()方法。
//person类
public class Person {
private String name;
private int age;
//重写hashCode()和 equals()方法
@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);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//main
public static void main(String[] args) {
Person person1 = new Person("阿明", 18);
Person person2 = new Person("阿明", 18);
Person person3 = new Person("阿明", 19);
HashSet<Person> people = new HashSet<>();
people.add(person1);
people.add(person2);
people.add(person3);
System.out.println(people);
}