一:

和List接口同一级的还有Set接口,Set类型的集合,元素不能重复,存储顺序和迭代顺序没有必然联系。他的元素的唯一性是由hasCode和equals决定的。

他的子类,常用的HashSet和LinkedHashSet。

 package test11;

 import java.util.HashSet;
import java.util.Iterator;
import java.util.Set; public class Hash_Demo {
public static void main(String[] args){
has_Test();
}
public static void has_Test(){
Set<String> set_str=new HashSet<>();
set_str.add("i");
set_str.add("j");
set_str.add("k");
set_str.add("k");
set_str.add("m");
Iterator<String> set_it=set_str.iterator();
while (set_it.hasNext()){
System.out.print(set_it.next());
}
}
}

对于我们常用的javaAPI (String、Ineteger等)的equals和hascode方法已经重写。

HashSet集合存储数据的结构:

首先我们了解什么是哈希表?

哈希表底层使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时的位置比较特殊,当需要把这些对象给数组中存放的时候,那么根据这些对象的特有的数据结合相应的算法,计算出这个对象在数据中的位置,然后把这个对象存放在数组中而这样的数组叫做哈希数组,也就是哈希表。

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

这也就是保证了HashSet集合的元素的唯一性,其实就是根据对象的hascode和equals方法决定的。如果我们往集合存储自定义对象的话,需要我们重写hashcode和equals方法,来适用当前对象比较方法。

对于javaAPI上面代码。

对于自定义类型,需要重写hascode和equals方法。

 package Id_Has;

 import java.util.HashSet;
import java.util.Iterator; public class Id_Set {
public static void main(String[] args){
HashSet<Person_Info> per_set=new HashSet<>();
per_set.add(new Person_Info("tom",));
per_set.add(new Person_Info("tom",));
Iterator<Person_Info> per_it=per_set.iterator();
while (per_it.hasNext())
{
System.out.print(per_it.next());
}
} } class Person_Info{
private String name;
private int age;
public Person_Info(String name,int age){
this.name=name;
this.age=age;
} public String getName() {
return name;
}
public int getAge(){
return age;
}
public boolean equals(Object obj){
if(obj==null){
return false;
}
if(obj==this){
return true;
}
if(obj instanceof Person_Info){
Person_Info new_obj=(Person_Info)obj;
if(new_obj.name.equals(this.name)&& new_obj.age==this.age){
return true;
}
}
return false;
}
public int hashCode(){
final int prime=;
int result=;
result=result*prime+age;
result=prime * result + ((name == null) ? : name.hashCode());
return result;
}
public String toString(){
return "Person_Info[" +this.name+" "+this.age + "]";
}
}

我们需要对equals方法进行重写以及hashCode方法。

equals方法:

     public boolean equals(Object obj){
if(obj==null){
return false;
}
if(obj==this){
return true;
}
if(obj instanceof Person_Info){
Person_Info new_obj=(Person_Info)obj;
if(new_obj.name.equals(this.name)&& new_obj.age==this.age){
return true;
}
}
return false;
}

hashCode方法:

     public  int hashCode(){
final int prime=;
int result=;
result=result*prime+age;
result=prime * result + ((name == null) ? : name.hashCode());
return result;
}

其中hashCode方法的重写,是参考JavaApi进行重写。

字符串的hashCode的重写,其中private int hash; // Default to 0  然后用h的值乘以31在和字符对应的数值进行计算得到一个整数作为字符串的hashCode。因为字符串这种保证了hashCode唯一性。然后我们重写的时候

其中有个值是唯一的就是name的hashCode。

总结如下:

hashCode相等的,不一定对象相等。

对象相等,hashCode相等,

HashSet的是无序的,存储和遍历,但是如果我们想要存取顺序的怎么办呢?

HashSet的子类有个子类:LinkedHashset。

public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, Serializable

他是链表和Hashset的结合。

code:

 package test11;

 import java.util.Iterator;
import java.util.LinkedHashSet; public class LinkHash_Demo {
public static void main(String[] args){
linkHashTest(); }
public static void linkHashTest(){
LinkedHashSet<String> link=new LinkedHashSet<>();
link.add("e");
link.add("f");
link.add("g");
link.add("i");
Iterator<String> linkit=link.iterator();
while (linkit.hasNext()){
System.out.print(linkit.next());
}
}
}

输出结果:

二:ArrayList中的判断元素是否重复原理:

非自定义类型,ArrayList在判断一个元素是否包含这个元素,使用的是contains()方法来判断,实际上使用的equals方法来进行判断,非自定义类型的数据类型equals方法都进行重写,自定义类型的数据需要自己重写的方法,

否则判断的是对象的内存地址是否相等。有时候我们判断一个对象是否相等,是通过对象的属性进行判断而不是单单内存地址,内存地址相等一定是同一个对象,但是对象的内存地址不相等并不能说明两个对象不相等。

最终通过equals来遍历数组判断是否有相等元素。

三:Hashset的add方法和contians方法

因为set集合是无序、唯一的。那set如何判断一个元素是否重复呢?

通过hashCode 和equals方法进行判断。首先计算出要添加元素的hashcode  然后跟集合里的元素的hashcode进行判断,如果不相等,则插入元素,如果相等的话,在和集合的元素进行equals方法的比较,返回true

则不添加元素,如果返回false的话,添加元素。

在对自定义类型的进行set操作的时候,需要重写equals和hashCode方法的重写。

总结:

     List与Set集合的区别?
List:
它是一个有序的集合(元素存与取的顺序相同)
它可以存储重复的元素
Set:
它是一个无序的集合(元素存与取的顺序可能不同)
它不能存储重复的元素
List集合中的特有方法
void add(int index, Object element) 将指定的元素,添加到该集合中的指定位置上
Object get(int index)返回集合中指定位置的元素。
Object remove(int index) 移除列表中指定位置的元素, 返回的是被移除的元素
Object set(int index, Object element)用指定元素替换集合中指定位置的元素,返回值的更新前的元素
ArrayList:
底层数据结构是数组,查询快,增删慢
LinkedList:
底层数据结构是链表,查询慢,增删快
HashSet:
元素唯一,不能重复
底层结构是 哈希表结构
元素的存与取的顺序不能保证一致
如何保证元素的唯一的?
重写hashCode() 与 equals()方法
LinkedHashSet:
元素唯一不能重复
底层结构是 哈希表结构 + 链表结构
元素的存与取的顺序一致

set集合HashSet的更多相关文章

  1. Java集合 -- HashSet 和 HashMap

    HashSet 集合 HashMap 集合 HashSet集合 1.1 Set 接口的特点 Set体系的集合: A:存入集合的顺序和取出集合的顺序不一致 B:没有索引 C:存入集合的元素没有重复 1. ...

  2. java集合-HashSet

    HashSet 概述 对于 HashSet 而言,它是基于 HashMap 实现的,底层采用 HashMap 来保存元素,所以如果对 HashMap 比较熟悉了,那么学习 HashSet 也是很轻松的 ...

  3. Java 集合 - HashSet

    一.源码解析 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable ...

  4. Java集合---HashSet的源码分析

    一.  HashSet概述: HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持.它不保证set 的迭代顺序:特别是它不保证该顺序恒久不变.此类允许使用null元素. 二.  ...

  5. Set集合——HashSet、TreeSet、LinkedHashSet(2015年07月06日)

    一.Set集合不同于List的是: Set不允许重复 Set是无序集合 Set没有下标索引,所以对Set的遍历要通过迭代器Iterator 二.HashSet 1.HashSet由一个哈希表支持,内部 ...

  6. 哈希集合——hashSet

    /**     哈希集合特点:存取顺序不确定,同一个哈希值的位置可以存放多个元素,                   哈希集合存放元素的时候是先判断哈希地址值:hashCode()是否相同,如果不同 ...

  7. ava集合---HashSet的源码分析

    一.HasnSet概述 Hashset实现set接口,由哈希表(实际上是一个HashMap实例)支持.它不保证set的迭代顺序.特别是它不保证该顺序恒久不变.此类允许使用Null元素 一.HasnSe ...

  8. java集合-HashSet源码解析

    HashSet 无序集合类 实现了Set接口 内部通过HashMap实现 // HashSet public class HashSet<E> extends AbstractSet< ...

  9. 集合-HashSet

    参考博客:https://www.cnblogs.com/runwulingsheng/p/5208762.html https://www.cnblogs.com/ysocean/p/6555373 ...

  10. 基于散列的集合 HashSet\HashMap\HashTable

    HashSet\HashMap\HashTable 1 基于散列的集合 2 元素会根据hashcode散列,因此,集合中元素的顺序不一定与插入的顺序一致. 3 根据equals方法与hashCode方 ...

随机推荐

  1. spring AOP 动态代理和静态代理以及事务

    AOP(Aspect Oriented Programming),即面向切面编程 AOP技术,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装 ...

  2. java Date 当天时间戳处理

    1. 代码 private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; private static Date ...

  3. DOM节点树和元素树--深度遍历

    我们在阅读JS高级程序设计的时候,提到了节点树的概念.比如说: elem.parentNode---找elem的父节点: elem.childNodes---找elem的所有的直接子节点: elem. ...

  4. bootstrapValidator验证中Maximum call stack size exceeded

    Tip1:如果表单不是通过Bootstrap构建(即元素包含表单项且关联的label没有form-group类),可能会看到错误Uncaught RangeError: Maximum call st ...

  5. 初学PS

    PS中的一些快捷键:新建:Ctrl+N 放大:Ctrl++ 缩小:Ctrl+- 首选项:Ctrl+K 标尺:Ctrl+R移动视图:空格键 绘制正圆:Shift 绘制鼠标落脚点为中心的正圆:Shift+ ...

  6. SystemLogParser ArcGIS Server运维工程师的好助手

    单位使用ArcGIS Server发布了众多GIS服务,作为系统运维工程师,一直希望能有一种便捷的方式能获得服务的访问情况,Esri推出的SystemLogParser这款小程序就是不错的辅助工具,而 ...

  7. linux rpm之已安装包校验、rpm包中文件提取

    已安装包校验 rpm -V 已安装的包名-V 校验指定rpm包中的文件 rpm -V pth没有任何提示,说明自安装后没有做过任何修改 rpm包中文件提取 比如对一个系统配置文件误操作,可以根据这个文 ...

  8. Charles基础

    一.Charles 监控其他设备连接方式 1.XP系统:控制面板——>Internet选项——>连接(tab)——>局域网(LAN)设置——>局域网设置——>代理服务器, ...

  9. 手动搭建 redis 集群

    转自http://meia.fun/article/1544161420745 手动搭建 redis 集群 redis 基本命令: 启动 redis 服务:redis-server xxx.conf ...

  10. java基础——队列

    目录 前言 基础 实现: 两个队列模拟一个堆栈 前言 java已经提供了堆和栈的相对应的类,这里只是模拟一下队列. 队列是一种先进先出的线性表. 基础 java5中新增加了java.util.Queu ...