一:

和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. python开发必备神器 Virtualenv及管理工具Virtualenvwrapper

    如果在一台机器上,想开发多个不同的项目,需要用到同一个包的不同版本,如果还在本地继续安装,在同一个目录下安装或者更新,其它的项目必须就无法运行了,怎么办呢? 解决方案:虚拟环境 虚拟环境可以搭建独立的 ...

  2. WEB前端常用JavaScript代码整理

    文章目录 html代码用JS动态加载进页面 JS判断用户访问的是PC还是mobile或者微信浏览器 判断浏览器的简单有效方法 点击某个div区域之外,隐藏该div 如何在手机上禁止浏览器的网页滚动 改 ...

  3. Unexpected token o in JSON at position 1 at JSON.parse (<anonymous>) SyntaxError: Unexpected token R in JSON at position 0 at JSON.parse (<anonymous>)

    这个问题在之前做项目时碰到过一次,当时按照网上的做法,去掉JSON.parse()这一层转换后就没有这个报错了,数据也能正常使用,就没多想,也没深究是什么原因.可是这次又碰到了,所以这次我必须要弄明白 ...

  4. android开启线程的误区

    发现一些刚学android的人,和我当初一样,对android的线程会存在着一定误区. 在android中,开启新线程时,一些人会用以下方法: new Handler().post(r); 但是这样并 ...

  5. import依赖范围的使用

    <!-- <parent> <groupId>org.springframework.boot</groupId> <artifactId>spr ...

  6. Django 模板语言 标签

    前言:django的模板语法基本和flask的jinja2基本一样.下面比较一下两个模板语法的区别. ------深度变量的查找(万能的句点号) 在 Django 模板中遍历复杂数据结构的关键是句点字 ...

  7. python实现字符串中的半全角转换

    全角和半角的空格的Unicode值相差12256 除空格外的全角和半角的Unicode值相差65248 # -*- coding: utf-8 -*- def strQ2B(ustring): &qu ...

  8. scrapy实战--登陆人人网爬取个人信息

    今天把scrapy的文档研究了一下,感觉有点手痒,就写点东西留点念想吧,也做为备忘录.随意写写,看到的朋友觉得不好,不要喷我哈. 创建scrapy工程 cd C:\Spider_dev\app\scr ...

  9. Hive的介绍及安装

    简介 Hive 是基于 Hadoop 的一个数据仓库工具,可以将结构化的数据文件 映射为一张数据库表,并提供类 SQL 查询功能. 本质是将 SQL 转换为 MapReduce 程序. Hive组件 ...

  10. [C# | XML] XML 反序列化解析错误:<xml xmlns=''> was not expected. 附通用XML到类解析方法

    使用 XML 反化时出现错误: public static TResult GetObjectFromXml<TResult>(string xmlString) { TResult re ...