一:

和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. 使用JSON实现分页

    使用JSON实现分页可直接用 Fenye.html <!DOCTYPE html> <html> <head> <title>JSON分页</ti ...

  2. 【代码笔记】iOS-iphone开发之获取系统字体

    代码: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. NS ...

  3. 仿饿了吗点餐界面两个ListView联动效果

    这篇文章主要介绍了仿饿了点餐界面2个ListView联动效果的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 如图是效果图: 是仿饿了的点餐界面 1.点击左侧的ListView,通过在在适 ...

  4. 在weblogic下部署找不到授权文件的解决方法

     很多用户在weblogic上部署的时候,会遇到类似的报错信息,提示授权找不到,解决这个问题的思路如下: 第一步确定授权的没有过期, 客户如果修改了系统时间,会对授权生效产生影响,在进行操作前先将 ...

  5. UltraPtr下拉刷新

    github:  https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh <in.srain.cube.views.ptr.PtrF ...

  6. 在Windows Server 2012中打开传统的磁盘管理界面

    在“运行”中输入diskmgmt.msc即可

  7. zabbix系列之三——安装报错

    1Zabbix_server启动失败 1.1查看日志:vi /var/log/zabbix/zabbix_server.log zabbix_server [23500]: cannot open l ...

  8. Jquery Ajax 提交json数据

    在MVC控制器(这里是TestController)下有一个CreateOrder的Action方法 [HttpPost] public ActionResult CreateOrder(List&l ...

  9. 关于Entity Framework关系配置,提示列名XXXX_Id无效的问题

    问题描述 : 数据库中有两张表,如下: Member(会员)表有外键RoleId,对应的是Role(角色)表的主键Id,业务逻辑是Member表的RoleId必须与Role表的Id对应(但在设计数据表 ...

  10. October 09th 2017 Week 41st Monday

    My motto is: Contended with little, yet wishing for more. 我的座右铭是:为一点点感到满足,但希望获得更多. If you can live y ...