Java学习笔记31(集合框架五:set接口、哈希表的介绍)

2018-01-13 by 一清

set接口的特点:

1.不包含重复元素

2.set集合没有索引,只能用迭代器或增强for循环遍历

3.set的底层是map集合

方法和Collection的方法基本一样

set接口的实现类HashSet:

1.无序集合

2.可以存入空(null)

3.不可以存在重复元素

示例:

package demo;import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class HashSetDemo { public static void main(String[] args) { Set<String> set = new HashSet<String>(); set.add("abc1"); set.add("abc1"); set.add("abc2"); set.add("abc3"); set.add("abc4"); Iterator<String> i1 = set.iterator(); while(i1.hasNext()){ System.out.println(i1.next()); } }}/*输出:注意:这里的输出特点是无序的abc1abc4abc2abc3*/

set底层数据结构是哈希表:

特点:存储取出都比较快

原理:具体省略,简单说就是链表数组结合体

对象的哈希值:普通的一个整数

可以理解为身份证号,是hashset存储的依据

package demo;public class Person {}package demo;public class HashDemo { public static void main(String[] args) { Person p = new Person(); int i = p.hashCode(); System.out.println(i); //每次运行都会输出不同的整数,比如1191201656 String s1 = new String("abc"); String s2 = new String("abc"); System.out.println(s1.hashCode());//96354 System.out.println(s2.hashCode());//96354 //这里Stirng重写hashcode方法,有对应的计算公式 //当字符串的内容相同时候,运算结果就相同,因此s1和s2的哈希值相同 }}

哈希表存储过程:


1.调用对象的哈希值

2.集合在容器内搜索有没有重复的哈希值,如果没有,存入新元素,记录哈希值

3.再次存储,重复上边的过程

4.如果有重复的哈希值,调用后来者的equals方法,参数为前来者,结果得到true,集合判断为重复元素,不存入

相同的字符串如果存进去,哈希值相同,equals方法为true,不会存入相同的

只要哈希值相同或者equals方法为true都成立才不会存入,只要其中一条不满足,都会储存

哈希表存储自定义对象:

package demo;public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString() { return this.name + ":" + this.age; } public Person() { } public Person(String name, int age) { super(); this.name = name; this.age = age; }}package demo;import java.util.HashSet;public class HashDemo { public static void main(String[] args) { HashSet<Person> setPerson = new HashSet<Person>(); setPerson.add(new Person("a",17)); setPerson.add(new Person("b",20)); setPerson.add(new Person("b",20)); setPerson.add(new Person("c",18)); System.out.println(setPerson); //[c:18, b:20, a:17, b:20] //发现存入了重复的元素 //所以想办法使name和age相同的Person对象视为同一个对象 //所以需要重写hashcode方法 }}

自己重写:

package demo;public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString() { return this.name + ":" + this.age; } public Person() { } public Person(String name, int age) { super(); this.name = name; this.age = age; } public int hashCode(){ return name.hashCode()+age*66; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (obj instanceof Person) { Person p = (Person) obj; return name.equals(p.name) && age == p.age; } return false; }}

eclipse可以帮助我们写:

package demo;public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString() { return this.name + ":" + this.age; } public Person() { } public Person(String name, int age) { super(); this.name = name; this.age = age; } @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; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; }}

LinkedHashSet集合:基于链表的哈希表实现,继承HashSet,它具有顺序

示例:

package demo;import java.util.LinkedHashSet;public class LinkedHashSetDemo { public static void main(String[] args) { //有序的set LinkedHashSet<Integer> link = new LinkedHashSet<Integer>(); link.add(1); link.add(2); link.add(3); link.add(4); System.out.println(link); //[1, 2, 3, 4] }}

关于hashcode和equals的一些问题,在面试中会问道:

1.两个对象哈希值相同,那么equals方法一定返回true吗?不一定

取决于如何重写equals,如果重写固定了它返回false,结果就一定是false

2.equals方法返回true,那么哈希值一定相同吗?一定

如果类中定义一个静态变量(static int a = 1),然后重写hashcode返回a+1,那么每一个对象的哈希值都不一样

不过java中规定:对象相等,必须具有相同的哈希码值,所以这里是一定的

最新更新:

第七城市

栏目导航(关闭)