set集合HashSet
一:
和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的更多相关文章
- Java集合 -- HashSet 和 HashMap
HashSet 集合 HashMap 集合 HashSet集合 1.1 Set 接口的特点 Set体系的集合: A:存入集合的顺序和取出集合的顺序不一致 B:没有索引 C:存入集合的元素没有重复 1. ...
- java集合-HashSet
HashSet 概述 对于 HashSet 而言,它是基于 HashMap 实现的,底层采用 HashMap 来保存元素,所以如果对 HashMap 比较熟悉了,那么学习 HashSet 也是很轻松的 ...
- Java 集合 - HashSet
一.源码解析 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable ...
- Java集合---HashSet的源码分析
一. HashSet概述: HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持.它不保证set 的迭代顺序:特别是它不保证该顺序恒久不变.此类允许使用null元素. 二. ...
- Set集合——HashSet、TreeSet、LinkedHashSet(2015年07月06日)
一.Set集合不同于List的是: Set不允许重复 Set是无序集合 Set没有下标索引,所以对Set的遍历要通过迭代器Iterator 二.HashSet 1.HashSet由一个哈希表支持,内部 ...
- 哈希集合——hashSet
/** 哈希集合特点:存取顺序不确定,同一个哈希值的位置可以存放多个元素, 哈希集合存放元素的时候是先判断哈希地址值:hashCode()是否相同,如果不同 ...
- ava集合---HashSet的源码分析
一.HasnSet概述 Hashset实现set接口,由哈希表(实际上是一个HashMap实例)支持.它不保证set的迭代顺序.特别是它不保证该顺序恒久不变.此类允许使用Null元素 一.HasnSe ...
- java集合-HashSet源码解析
HashSet 无序集合类 实现了Set接口 内部通过HashMap实现 // HashSet public class HashSet<E> extends AbstractSet< ...
- 集合-HashSet
参考博客:https://www.cnblogs.com/runwulingsheng/p/5208762.html https://www.cnblogs.com/ysocean/p/6555373 ...
- 基于散列的集合 HashSet\HashMap\HashTable
HashSet\HashMap\HashTable 1 基于散列的集合 2 元素会根据hashcode散列,因此,集合中元素的顺序不一定与插入的顺序一致. 3 根据equals方法与hashCode方 ...
随机推荐
- JAVA 判断字符串是否可转化为JSONObject、JSONArray
有时,我们需要判断字符串在转化为JSON对象或者JSONArray时,我们可以使用JSONObject.parseObject和JSONArray.parseArray,但是有时候我们需要在转化之前判 ...
- Strut2开发经验总结
1.如何在html静态页面中使用struts tomcat目录/conf/web.xml 文件中,找到 <servlet-mapping> <servlet-name>jsp& ...
- Spring Boot—08Jackson处理JSON
package com.sample.smartmap.controller; import java.io.IOException; import java.math.BigDecimal; imp ...
- c# 从一个服务器 访问另外一个服务器上的文件
页面调用 function fnOpen(path) { window.open("~/FileHelp.ashx? url="); //window.open(url); } 后 ...
- react-ssr
为什么使用SSR 与传统 SPA(Single-Page Application - 单页应用程序)相比 服务器端渲染(SSR)的优势主要在于: 更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完 ...
- 如何计算tomcat线程池大小?
背景 在我们的日常开发中都涉及到使用tomcat做为服务器,但是我们该设置多大的线程池呢?以及根据什么原则来设计这个线程池呢? 接下来,我将介绍本人是怎么设计以及计算的. 目标 确定tomcat服务器 ...
- IIS 中托管基于TCP绑定的WCF服务
IIS 中托管基于TCP绑定的WCF服务 一.创建一个基于TCP绑定的WCF服务 1.创建一个的简单的服务具体代码如下 服务契约定义 namespace SimpleService { // 注意: ...
- IPv4到IPv6的三种过渡技术
1. 双协议栈 ( Dual Stack, RFC2893 ) 主机同时运行IPv4和IPv6两套协议栈,同时支持两套协议. 2. 隧道技术 ( Tunnel, RFC2893 ) 这种机制用来在IP ...
- 从零开始导入gradle项目
需要jdk1.8,idea17以上,电脑安装gradle(配置环境变量,与配置java类似),用git的push命令下项目,开始操作 gradle配置本地仓库位置:添加环境变量GRADLE_USER_ ...
- 自定义UITabbarController控制器
自定义UITabbarController控制器 这是定制UITabbarController的基本原理,没有进行功能性封装. 效果: 源码地址: https://github.com/YouXi ...