学习笔记之JavaSE(32)--JavaAPI详解7
来源:互联网 发布:java物联网待遇 编辑:程序博客网 时间:2024/06/02 18:17
今天学习的内容是集合类之HashSet和LinkedHashSet
与List接口不同,Set接口与Collection接口的方法完全一致。常用的集有HashSet、LinkedHashSet和TreeSet,今天先学习HashSet和LinkedHashSet。
HashSet的底层数据结构是哈希表,是不同步的。HashSet在存储元素时是以该元素的哈希值确定存储位置,在随机访问集中的元素时,不需要从头开始查找,根据哈希值就可以快速找到元素,所以HashSet提供了最快的查询速度。注意HashSet可以存储null。
那么HashSet是如何判断元素是否重复呢?在存储元素时,HashSet会先调用该元素的HashCode()方法得到该元素的哈希值,与集中元素的哈希值比较,判断该元素是否与集中的元素重复,如果不重复就直接存储该元素。但是由于算法的原因,不同对象的哈希值有可能相同,所以如果该元素的哈希值与集中某元素相同,HashSet还要使用equals()方法比较这两个元素是否相等。如果返回true,不会存储该元素;如果返回false,此时可以选择顺延或者串联存储。所以,当使用集存储自定义类的对象时,必须要覆盖HashCode()方法与equals()方法。
由于HashSet是根据哈希值确定元素的存储位置,所以HashSet是无序的。针对这个问题,JavaAPI提供了一个HashSet的子类:LinkedHashSet,它的底层数据结构是链表和哈希表,所以LinkedHashSet是有序的,元素的顺序就是添加的顺序。
HashSet和LinkedHashSet的示例程序如下:
public class Test55 {public static void main(String[] args) {// HashSet的方法都是Collection的方法HashSet<String> set = new HashSet<>();set.add("a");set.add("a");set.add("b");set.add("c");System.out.println(set);// [b, c, a] 元素不允许重复,且元素是无序的Iterator<String> it = set.iterator();while (it.hasNext()) {// 由于Set接口没有定义get()方法,所以只能用这种方式获取元素System.out.print(it.next());// bca}// LinkedHashSet是有序的LinkedHashSet<String> l_set = new LinkedHashSet<>();l_set.add("a");l_set.add("a");l_set.add("b");l_set.add("c");System.out.println(l_set);// [a, b, c] 元素不允许重复,且元素是有序的// 使用HashSet存储自定义对象HashSet<Person> hs = new HashSet<>();hs.add(new Person("张三", 21));hs.add(new Person("张三", 21));hs.add(new Person("李四", 21));hs.add(new Person("王五", 21));System.out.println(hs);// [Person [name=王五, age=21], Person [name=张三,// age=21], Person [name=李四, age=21]]Iterator<Person> it_p = hs.iterator();while (it_p.hasNext()) {Person p = it_p.next();System.out.println(p);// 具有相同name和age的Person对象会被视作同一个对象,不会重复存储}}}// 要覆盖Person的hashCode()与equals()方法class Person {private String name;private int age;public Person() {super();}public Person(String name, int age) {super();this.name = name;this.age = 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;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}@Overridepublic int hashCode() { // 覆盖Object的hashCode()方法final int prime = 31;int result = 1;result = prime * result + age;result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {// 覆盖Object的equals()方法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;}}
补充一点,列表判断元素是否相等(比如调用contains()方法时)只判断equals()方法,如下示例程序:
public class Test56 {public static void main(String[] args) {// 定义一个临时列表存储不重复的元素ArrayList<Person> al = new ArrayList<>();al.add(new Person("张三", 21));al.add(new Person("张三", 21));al.add(new Person("李四", 21));al.add(new Person("王五", 21));System.out.println(al);// 会存储相同name与age的Person对象al = getSingleElement(al);//调用了四次equals()方法System.out.println(al);// 不存储相同name与age的Person对象}public static ArrayList<Person> getSingleElement(ArrayList<Person> al) {// 定义一个临时列表ArrayList<Person> temp = new ArrayList<>();// 迭代alIterator<Person> it = al.iterator();while (it.hasNext()) {Person p = it.next();// 判断该元素是否存在于临时列表中,如不存在,添加进临时列表if (!temp.contains(p)) {// 列表判断元素相同的依据:只判断equals()方法temp.add(p);}}return temp;}}class Person {private String name;private int age;public Person() {super();}public Person(String name, int age) {super();this.name = name;this.age = 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;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}@Overridepublic int hashCode() { // 覆盖Object的hashCode()方法System.out.println("hashCode()");return age;}@Overridepublic boolean equals(Object obj) {// 覆盖Object的equals()方法System.out.println("equals()");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;}}
- 学习笔记之JavaSE(32)--JavaAPI详解7
- 学习笔记之JavaSE(26)--JavaAPI详解1
- 学习笔记之JavaSE(29)--JavaAPI详解4
- 学习笔记之JavaSE(30)--JavaAPI详解5
- 学习笔记之JavaSE(31)--JavaAPI详解6
- 学习笔记之JavaSE(33)--JavaAPI详解8
- 学习笔记之JavaSE(34)--JavaAPI详解9
- 学习笔记之JavaSE(35)--JavaAPI详解10
- 学习笔记之JavaSE(36)--JavaAPI详解11
- 学习笔记之JavaSE(37)--JavaAPI详解12
- (黑马程序员)学习笔记,javaAPI之String
- 学习笔记之JavaSE(7)--Java基础语法6
- 学习笔记之JavaSE(8)--Java基础语法7
- 学习笔记之JavaSE(16)--面向对象编程7
- 学习笔记之JavaSE(45)--IO流7
- JavaSE学习笔记之Annotation(注解)
- 学习笔记之JavaSE(38)--泛型
- HDFS学习笔记(2)hdfs_shell & JavaAPI
- 分布式架构的演进
- 使用谷歌官annotation包的时候出现错误
- 更换用户名登录共享文件夹
- range与xrange
- [Android]取消GridView点击item时的颜色(我的手机点击后是橙黄色)
- 学习笔记之JavaSE(32)--JavaAPI详解7
- Ajax XMLHttpRequest对象的三个属性以及open和send方法
- 我也开始写博客了
- 有关文件的小练习题
- Quartz学习之Lesson6-CronTrigger
- 分页效果
- js实现tab切换以及自动切换
- html5存储
- python数据分析pandas包入门学习(四)处理缺失数据