`
jiq408694711
  • 浏览: 36593 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

HashMap和HashSet深度解析

 
阅读更多
package container;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;

/**
 * @author jiq408694711@163.com
 *  
 *  测试HashSet中,通过equals方法检测到重复之后会发生什么。
 *  以及测试hashCode函数生成的散列码相同之后,会不会被去掉。
 *
 */
class TestObject{
	int x;
	int y;
	public TestObject(int x, int y){
		this.x = x;
		this.y = y;
	}
	
	/* 一般重写equals方法的同时也会重写hasCode方法,为什么? */
	public int hashCode(){
		return x;
	}
	
	/* 注意参数是Object类型,否则就不是覆盖了 */
	public boolean equals(Object obj) {
		TestObject oo = (TestObject)obj;
		return (this.x == oo.x)?true:false;
	}
}

public class HashSetTest {

	public static void main(String args[]){
		/**
		 * 重写了Object的equals方法,只要两个对象x字段相等,
		 * 那么两个对象就相等。(默认的equals方法是比较引用==)
		 * (注意: 引用仍然不同,即不是指向同一个对象)
		 */
		TestObject o1 = new TestObject(1,3);
		TestObject o2 = new TestObject(3,3);
		System.out.println(o1.equals(o2));
		System.out.println(o1 == o2);
		
		/**
		 *  HashMap,采用数组散列存储,散列值有hashCode返回,
		 *  同一个hashCode的对象,采用链接法解决冲突。通过equals判断是否冲突。
		 *  下面是HashMap内部的put方法的实现。
		 * 	public V put(K key, V value) {
		        if (key == null)
		            return putForNullKey(value);
		        int hash = hash(key.hashCode()); 		//生成hash值
		        int i = indexFor(hash, table.length);	//找到该hash值在数组中位置索引
		       
		        //循环该hash槽的所有对象
		        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
		            Object k;
		            //如果equals()方法返回true,发现“重复”
		            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
		                V oldValue = e.value;
		                e.value = value; 	//将新的值替换原来的值,键不动
		                e.recordAccess(this);
		                return oldValue;
		            }
		        }

		        modCount++;
		        addEntry(hash, key, value, i);
		        return null;
    		}
		 * */	
		HashMap<TestObject,String> map = new HashMap<TestObject,String>();
		//键hashCode相同,且equals返回true,故替换值,可以看到键没有变化
		map.put(new TestObject(1,0), "XXX");	
		map.put(new TestObject(1,2), "YYY");
		System.out.println("MAP SIZE:"+map.size());
		for(Entry<TestObject,String> e: map.entrySet()){
			System.out.println(e.getKey().x+","+e.getKey().y+","+e.getValue());
		}
		
		/**
		 *  HashSet通过HashMap实现,键就是插入的对象,而值统一是一个static的Object
		 *  下面是add方法的实现。
		 * 	public boolean add(E e) {
				return map.put(e, PRESENT)==null;
    		}
		 * */
		HashSet<TestObject> set = new HashSet<TestObject>();
		set.add(new TestObject(1,2));
		//hashCode方法和equals方法都返回相同值,所以替换值,但是它的值部分只是一个static的Object
		set.add(new TestObject(1,1));
		set.add(new TestObject(3,1));
		set.add(new TestObject(3,4));
		
		System.out.println("SET SIZE:"+set.size());
		for(TestObject o: set){
			System.out.println(o.x+","+o.y);
		}
		
		/*
		 * 注意,HashCode返回的值决定了你的存在散列表中的Entry对象应该在哪个槽位
		 * 设想如果你的equals方法重写了,认为两个对象相等,但是hashCode返回的两个对象
		 * 的值却不一样,那么他们都不可能在一个槽位,所以equals方法就没意义。
		 * 
		 * 所以我们重写键对象的equals方法的时候,一般同时重写hashCode方法。
		 * 尽量保证: 
		 * (1)当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true
		 * (2)当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false
		 */
		
		/**
		 * 拓展: 如果吧TestObject的equals方法改成return (this.y == oo.y)?true:false;
		 * 那么	set.add(new TestObject(1,2));
				set.add(new TestObject(1,1));
				set.add(new TestObject(3,1));
				会发生什么?输出set大小是多少?答案是3
		 * 	因为前两个对象虽然hashCode相同,但是equals返回false,故不是冲突的对象
		 *  后两个虽然equals返回了true,但是不是存在同一个槽位的对象,故也不是冲突对象。
		 * */
	}
}

输出:

false
false
MAP SIZE:1
1,0,YYY
SET SIZE:2
1,2
3,1

分享到:
评论

相关推荐

    Java集合框架深度解析:Map, List, Set

    深入的洞察到Java集合框架的核心组件:Map, List, 和 Set。...接着,文件转向List和Set的实现,特别是ArrayList和HashSet。这些集合的内部结构和特性,例如动态扩容和哈希机制,都是优化Java程序性能的关键。

    JAVA2深度历险.pdf

    集合框架是Java中处理数据结构的关键部分,如ArrayList、LinkedList、HashMap、HashSet等,它们的工作原理和高效使用技巧都是进阶学习的重点。多线程则是Java的一个强大特性,书中可能会讲解线程的创建、同步、锁...

    Java深度历险

    - 深入解析ArrayList、LinkedList、HashMap、HashSet等常用集合类的内部实现,以及它们的性能特点和适用场景。 9. **IO与NIO** - 介绍传统的Java IO流体系,以及后来引入的非阻塞IO(NIO)和新NIO.2 API,包括...

    Java参考大全

    《Java参考大全》是一本深度解析Java编程语言的权威指南,涵盖了广泛的Java技术主题,旨在帮助读者全面理解和掌握Java编程的核心概念与实践技巧。书中所包含的源代码是作者为了辅助讲解各种Java特性、设计模式以及...

    Java面试通关宝典:深度解读核心知识点与实战技巧,全面提升面试表现力与技术实力

    HashMap和HashSet分别用于存储键值对和无序唯一元素,它们依赖于哈希函数,HashMap处理哈希冲突通常采用开放寻址法或链地址法。 多线程与并发是Java面试的另一重点。Java提供了线程模型,包括同步机制(如...

    数据结构与算法经典问题解析 java语言描述 原书第二版

    6. **哈希表**:通过散列函数实现快速查找的数据结构,Java中的HashMap和HashSet是其具体实现。 在算法部分,本书将详细讲解以下内容: 1. **排序算法**:包括冒泡排序、选择排序、插入排序、快速排序、归并排序、...

    java源码课件框架学习

    在学习过程中,源码课件能提供实践案例和深度解析,帮助我们更好地理解和运用这些知识。例如,通过分析Spring框架的源码,我们可以学习到如何设计和实现一个强大的、可扩展的框架。同时,课件中的实例和练习将巩固...

    java深度历险

    4. **集合框架**:详述ArrayList、LinkedList、HashMap、HashSet等常用集合类的内部实现及操作方式,以及泛型、迭代器和并发容器的使用。理解集合框架可以帮助编写更高效、更安全的代码。 5. **IO流与NIO**:讲解...

    Java面试题(最全,最新)

    面试中常见的问题可能涉及类与对象、封装、继承和多态的概念,以及如何有效地使用ArrayList、LinkedList、HashMap和HashSet等集合类。异常处理是另一个重点,理解try-catch-finally结构以及不同类型的异常类是基础。...

    java数据结构与算法

    8. 动态规划、贪心算法和分治策略的实例解析和Java代码实现。 9. 数据结构和算法的性能分析,如时间复杂度和空间复杂度的计算。 通过学习这个资源包,你将能够深入理解Java中的各种数据结构和算法,提升编程技能,...

    Android+上百实例源码分析以及开源分析+集合打包3

    再者,"集合打包3"可能指的是针对Android中数据集合类的深度解析,包括ArrayList、LinkedList、HashMap、HashSet等。这些数据结构在Android应用中广泛使用,理解它们的底层实现原理和性能特性,能够帮助开发者选择最...

    数据结构教程(java语言描述)-源码和课件-李春葆

    配合李春葆教授的课件,你可以深入理解这些概念,课件通常包含PPT演示、例题解析和习题解答,帮助你巩固理论知识并提升实践能力。通过阅读源码,你可以看到这些数据结构和算法在实际编程中的应用,加深对Java编程的...

    课程课程

    ArrayList、LinkedList、HashSet、HashMap等集合类提供了存储和操作数据的能力。了解它们的特点和适用场景,可以有效提高代码效率。 I/O流是Java处理输入输出的重要工具,分为字节流和字符流,包括文件操作、网络...

    《Java2程序设计实用教程(第2版)》课件

    《Java2程序设计实用教程(第2版)》是一本深度解析Java编程的教材,针对初学者和进阶者提供全面而深入的指导。该教材旨在帮助读者掌握Java语言的核心概念和技术,为软件开发打下坚实的基础。标签“java教材”明确了这...

    JDK使用参考书.rar

    3. **集合框架**:介绍ArrayList、LinkedList、HashMap、HashSet等集合类的使用,以及泛型、迭代器和流的使用。 4. **异常处理**:讨论何时何地抛出异常,如何捕获和处理异常,以及自定义异常的创建。 5. **输入/...

    .net试题,JAVA面试题目

    4. **Java集合框架**:ArrayList、LinkedList、HashMap、HashSet等数据结构的使用和性能分析是常见问题。 5. **多线程**:Java并发编程,包括线程同步、线程池、锁机制等,是考察高级Java开发者的重要领域。 接...

    2019年蚂蚁课堂-余胜军主编Java工程师面试宝典-V1.0.pdf

    深入讲解了异常处理、集合框架(如ArrayList、LinkedList、HashMap、HashSet等)以及I/O流的使用。此外,还详细阐述了线程和并发编程,这是Java程序员必须掌握的重要技能,涉及到线程的创建、同步、死锁等问题。 ...

    蓝桥杯Java B组历年真题的源码及解析(2013-2017)

    3. **集合框架**:Java集合框架如ArrayList、LinkedList、HashMap、HashSet等的使用,以及它们之间的区别和选择,是解决许多问题的关键。 4. **IO流**:文件读写、输入输出操作是编程中常见的任务,理解和熟练运用...

    Java面试题进一步提升

    3. **集合框架**:Java集合框架包括List、Set、Map等接口及其实现类,如ArrayList、LinkedList、HashMap、HashSet等。面试中可能会要求实现特定功能,如查找、排序、去重等,或者分析它们的时间复杂度。 4. **多...

    JAVA实例大全 很不错的书

    其次,书中可能会深入探讨Java集合框架,如ArrayList、LinkedList、HashMap、HashSet等容器类的使用方法和场景选择,以及泛型、接口、抽象类的应用。这些内容在实际开发中极其常见,熟练掌握能显著提高代码质量。 ...

Global site tag (gtag.js) - Google Analytics