一、set接口

概念:set接口继承自Collection接口,与List接口不同的是,set接口所储存的元素是不重复的。

二、HashSet集合

概念:是set接口的实现类,由哈希表支持(实际上是一个HashMap集合)。HashSet集合元素的提取顺序与存储顺序不相同。

   采用哈希表数据结构存储数据,保证元素唯一性的方式依赖于:hashCode()与equals()方法。

2.1哈希表

  什么是哈希表? 链表与数组的组合。

  哈希表底层使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时的位置比较特殊,当需要把这些对象给数组中存放时,

那么会根据这些对象的特有数据结合相应的算法,计算出这个对象在数组中的位置,然后把这个对象存放在数组中。而这样的数组就称为哈希数组,即就是哈希表。

  当向哈希表中存放元素时,需要根据元素的特有数据结合相应的算法,这个算法其实就是Object类中的hashCode方法。由于任何对象都是Object类的子类,所以任何对象有拥有这个方法。即就是在给哈希表中存放对象时,会调用对象的hashCode方法,算出对象在表中的存放位置,这里需要注意,如果两个对象hashCode方法算出结果一样,这样现象称为哈希冲突,这时会调用对象的equals方法,比较这两个对象是不是同一个对象,如果equals方法返回的是true,那么就不会把第二个对象存放在哈希表中,如果返回的是false,就会把这个值存放在哈希表中。

  总结:保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。

  Hashcode方法用来计算哈希值。

hashCode方法计算图:

哈希表数组和链表的结合图:

2.2HashSet存储JavaAPI中的类型元素

给HashSet中存储JavaAPI中提供的类型元素时,不需要重写元素的hashCode和equals方法,因为这两个方法,在JavaAPI的每个类中已经重写完毕,如String类、Integer类等。

练习实例:

1.向哈希表添加元素并且打印

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet; public class Demo01 {
//哈希表
public static void main(String[] args) {
// TODO Auto-generated method stub
method1();
     method2();
     method3();
     method4();
}
public static void method1(){
HashSet<String> set=new HashSet<String> ();
set.add("abc");
set.add("abc");
set.add("ghi");
System.out.println(set); //
}

打印结果:因为唯一性,所以只存储了一个“abc”.

2.打印哈希值

//hashcode 方法(object类中提供)
public static void method2(){
String s1=new String("abc");
String s2=new String("abc");
//运行出来的 叫哈希值 运行的hashcode是string类的
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
}

打印结果:哈希值  hashCode()

3.向哈希表中添加自定义类的元素并打印

自定义Person类:

public class Person {
private String name;
private int age;
public Person(){ }
//重载构造方法,创建时赋值
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
} @Override
//转为字符串
public String toString() {
return "Person [name=" + name + ", 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;
}
@Override
//重写hashCode()方法
public int hashCode() { return name.hashCode()+age*31;
}
@Override
//重写equals()方法
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;
}
}

测试类方法:

public static void method3(){
HashSet<Person> set=new HashSet<Person>();
set.add(new Person("a",20));
set.add(new Person("a",10));
set.add(new Person("b",30));
set.add(new Person("b",30));
System.out.println(set);
}

运行结果:因为重写了hashCode方法跟equals方法  所以重复的元素并没有存储到集合中

三、LinkedHashSet集合:

我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?

在HashSet下面有一个子类LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。

实例:迭代器遍历有序唯一输出:

//迭代器遍历有序唯一输出
public static void method4(){
LinkedHashSet<String> set=new LinkedHashSet <String>();
set.add("a");
set.add("aabbb");
set.add("张三");
set.add("李四");
set.add("a");
set.add("李四");
Iterator it=set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}

运行结果:按照存储顺序打印

四、 判断集合元素唯一的原理

 4.1ArrayList的contains方法判断元素是否重复原理

ArrayList的contains方法会使用调用方法时,传入的元素的equals方法依次与集合中的旧元素所比较,从而根据返回的布尔值判断是否有重复元素。

(true则有,false则无)。此时,当ArrayList存放自定义类型时,由于自定义类型在未重写equals方法前,判断是否重复的依据是地址值,

所以如果想根据内容判断是否为重复元素,需要重写元素的equals方法。

4.2HashSet的add/contains等方法判断元素是否重复原理

Set集合不能存放重复元素,其添加方法在添加时会判断是否有重复元素,有重复不添加,没重复则添加。

HashSet集合由于是无序的,其判断唯一的依据是元素类型的hashCode与equals方法的返回结果。规则如下:

先判断新元素与集合内已经有的旧元素的HashCode值

l  如果不同,说明是不同元素,添加到集合。

l  如果相同,再判断equals比较结果。返回true则相同元素;返回false则不同元素,添加到集合。

所以,使用HashSet存储自定义类型,如果没有重写该类的hashCode与equals方法,则判断重复时,使用的是地址值,如果想通过内容比较元素是否相同,

需要重写该元素类的hashcode与equals方法。

最新文章

  1. pointers on c (day 1,chapter2)
  2. SQL知识整理三:变量、全局变量、视图、事务、异常
  3. C# 检测操作系统是否空闲,实现系统空闲后做一些操作
  4. ios实现类似魔兽小地图功能 在
  5. bzoj3203
  6. 2.MySQL入门基本操作初体验
  7. PHP利用超级全局变量$_POST来接收表单数据。
  8. Linux_shell条件判断if中的-a到-z的意思
  9. 【转】Linux 中断学习之小试牛刀篇
  10. Java-----instanceof、isInstance、isAssignableFrom
  11. [论文解读]CNN网络可视化——Visualizing and Understanding Convolutional Networks
  12. Spring MVC知识
  13. django url 反响解析,视图
  14. [2003_p1]乒乓球
  15. Collections.sort排序
  16. UIScrollView的AutoLayout约束
  17. PermGen space 内存溢出
  18. Nginx简单的负载均衡入门
  19. MVP模式在Android中的使用
  20. 关于Ubuntu拒绝root用户ssh远程登录

热门文章

  1. Rsync实现文件同步的算法(转载)
  2. [USACO4.3]逢低吸纳Buy Low, Buy Lower
  3. bzoj千题计划150:bzoj2738: 矩阵乘法
  4. 《A First Course in Abstract Algebra with Applications》-chaper1-数论-棣莫弗定理
  5. 【转】Ubuntu+apache绑定多个域名
  6. 穷竭搜索:POJ 3187 Backward Digit Sums
  7. Java并发编程原理与实战三十二:ForkJoin框架详解
  8. div+css+jQuery简单实现投票功能
  9. 实现asp.net的文件压缩、解压、下载
  10. 一些达成共识的JavaScript编码约定[转]