Java Map 怎样实现Key 的唯一性?

大家都知道。在Map和Set不可存在反复元素?

可是对于内部的细节我们并不了解。今天我们就一块来 探讨一下!

1 对于 HashMap  HashSet

他们的底层数据结构的实现是:维护了一张  HashTable 。容器中的元素所有存储在Hashtable 中。他们再加入元素的时候,是怎样推断是否存在有反复元素的呢?  每个被加入的元素都有一个 hashCode(哈希值),他们先比較哈希值,是否同样? 不同样的元素,加入进入 HashTable.   假设hashCode同样的话, 再去比較 equals()方法,假设也同样的话,JVM就觉得数据已经存在了。就不会加入数据!

如图1:

2 对于 TreeMap  TreeSet

他们底层是数据结构的实现是:维护了一棵二叉树。 容器中加入元素的时候,他们有是怎么推断是否有同样元素的?我们都直到 TreeMap TreeSet  她们 都是 有序的存储数据。

为了维护 数据的唯一性。 再存入数据的时候,他们会调用元素中 实现的 Comparable 的 compareTo()  方法(代码1)。 或者 集合本身创建的时候 传入了 迭代器(代码2).  详细的实现是:调用比較方法,返回-1
的时候,加入到左子树,返回1 的时候 加入到 右子树。

返回0 有同样数据 不加入该元素!

如图2

代码1;(原理一)

package stu.love.v;

import java.util.*;
//什么时候用Map
/*
当存在映射关系时。
每一个学员都相应一个地址
姓名,年龄同样的视为同一个人

*/
// 容器中的对象 本身 具备比較性。

class StudentD implements Comparable<StudentD>
{
	private String name;
	private int age;

	public StudentD(String name,int age)
	{
		this.name = name;
		this.age = age;
	}

	public int compareTo(StudentD stu)
	{
		int t = this.age-stu.age;
		return t==0?

this.name.compareTo(stu.name):t;
	}

//	重写了 hashCode 方法
    public int hashCode()
	{
	    return name.hashCode()+age*36;
	}

//    重写了  equals 方法
    public boolean equals(Object obj)
    {
	   if(!(obj instanceof StudentD))
	        throw new ClassCastException("类型异常");

	   	StudentD stu =(StudentD)obj;
		return this.name.equals(stu.name) && this.age ==stu.age;
	}

	public void setName(String name)
	{
		this.name = name;
	}
	public void setAge(int age)
	{
		this.age = age;
	}
	public String getName()
	{
		return this.name;
	}
	public int getAge()
	{
		return this.age;
	}
	public String toString()
	{
		return this.name +","+age;
	}
}
class Demo16
{
	public static void main(String[] args)
	{
		//保证键唯一的原理,先推断哈希值是否同样,同样再推断equals()
		HashMap<StudentD,String> hm = new HashMap<StudentD,String>();

		hm.put(new StudentD("xiaobai",23),"shanghai");
		hm.put(new StudentD("wanghei",20),"beijing");
		hm.put(new StudentD("lisi",28),"shenzhen");
		hm.put(new StudentD("lisi",28),"shenzhen");

//		Map 第一种 迭代方式   依据 key 找  value
		Set<StudentD> set=hm.keySet();
		for(Iterator<StudentD>  ite = set.iterator();ite.hasNext();)
		{
			StudentD stu = ite.next();
			String value = hm.get(stu);
			sop(stu+"的地址是:"+value);
		}

//		map 的 另外一种 迭代方式  获取 键值对。entry 获取当中的 key 和 value
		Set<Map.Entry<StudentD,String>> entry = hm.entrySet();
		for(Iterator<Map.Entry<StudentD,String>> ite = entry.iterator();ite.hasNext();)
		{
			Map.Entry<StudentD,String> kv = ite.next();
			StudentD key = kv.getKey();
			String  value = kv.getValue();
			sop(key+"的地址是:"+value);
		}

	}

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

代码2:

package stu.love.v;

/*
TreeMap:
HashMap保证键唯一的原理和HashSet同样
TreeMap保证键唯一的原理和TreeSet同样

*/
import java.util.*;

class Student1
{
	private String name;
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	private int age;

	public Student1(String name,int age)
	{
		this.name = name;
		this.age = age;
	}

	public String toString()
	{
		return name+","+age;
	}

}

//  比較器
class CompareByName implements Comparator<Student1>
{
	public int compare(Student1 s1,Student1 s2)
	{
//		这样写的方法 很好!

简洁
		int t = s1.getName().compareTo(s2.getName());
		return t ==0?s1.getAge()-s2.getAge():t;
	}
}

class  Demo17
{
	public static void main(String[] args)
	{
//		原理二:
		//保证键唯一的原理:比較方法的返回值为0
		TreeMap<Student1,String> tm = new TreeMap<Student1,String>(new CompareByName());

		tm.put(new Student1("xiaobai",23),"shanghai");
		tm.put(new Student1("wanghei",20),"beijing");
		tm.put(new Student1("lisi",28),"shenzhen");
		tm.put(new Student1("lisi",28),"shenzhen");

		Set<Map.Entry<Student1,String>> entry = tm.entrySet();

		for(Iterator<Map.Entry<Student1,String>> it = entry.iterator();it.hasNext();)
		{
			Map.Entry<Student1,String> kv = it.next();
			Student1 key = kv.getKey();
			String  value = kv.getValue();
			sop(key+"的地址是:"+value);
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
时间: 2024-10-08 09:46:18

Java Map 怎样实现Key 的唯一性?的相关文章

Java Map 如何实现Key 的唯一性?

大家都知道,在Map和Set不可存在重复元素? 但是对于内部的细节我们并不了解,今天我们就一块来 探讨一下! 1 对于 HashMap  HashSet 他们的底层数据结构的实现是:维护了一张  HashTable .容器中的元素全部存储在Hashtable 中.他们再添加元素的时候,是如何判断是否存在有重复元素的呢?  每一个被添加的元素都有一个 hashCode(哈希值),他们先比较哈希值,是否相同? 不相同的元素,添加进入 HashTable.   如果hashCode相同的话, 再去比较

java Map使用Object 做为Key的问题

近期在看dnsjava 源码的时候,不经意间发现一个自己没有想过的问题: HashMap 如何使用key去查找对应的value的,这个问题很难用语言描述的清楚,那就使用代码来进行说明吧! public class test { public static void main(String[] args) { a aa = new a(); b bb = new b(); Map<Object,Object> c = new HashMap<Object,Object>(); c.p

Java Map获取key和value 以及String字符串转List方法

一.问题描述 这里描述两个问题: 1.Java Map获取key和value的方法: 2.String字符串转List的方法: 二.解决方法 1.Java Map获取key和value的方法   2.String字符串转List的方法  

Java Map集合利用比较器Comparator根据Key和Value的排序

TreeMap排序 根据Key进行排序 Map的根据key排序需要用到TreeMap对象,因为它是默认按照升序进行输出的,可以使用比较器compareTo对它进行降序排序,Comparator可以对集合对象或者数组进行排序的比较器接口,实现该接口的public compare(T o1,To2)方法即可实现排序,该方法主要是根据第一个参数o1,小于.等于或者大于o2分别返回负整数.0或者正整数,若是按照升序可以直接省略比较器代码Map<String, String> treeMap = new

[Java] MAP、LIST、SET集合解析

在JAVA的util包中有两个所有集合的父接口Collection和Map,它们的父子关系: java.util        +Collection 这个接口extends自 --java.lang.Iterable接口           +List 接口               -ArrayList 类              -LinkedList 类              -Vector 类     此类是实现同步的 +Queue 接口              +不常用,在

java Map排序(升序、降序、随机排序)

基础知识: 1 HashMap会使用key,根据hashcode进行默认排序. 2  LinkedHashMap根据存入先后进行排序 代码展示: 1 随机排序 java Map排序(升序.降序.随机排序),布布扣,bubuko.com

Java Map遍历方式的选择

1. 阐述 对于Java中Map的遍历方式,很多文章都推荐使用entrySet,认为其比keySet的效率高很多.理由是:entrySet方法一次拿到所有key和value的集合:而keySet拿到的只是key的集合,针对每个key,都要去Map中额外查找一次value,从而降低了总体效率.那么实际情况如何呢? 为了解遍历性能的真实差距,包括在遍历key+value.遍历key.遍历value等不同场景下的差异,我试着进行了一些对比测试. 2. 对比测试 一开始只进行了简单的测试,但结果却表明k

Java Map

package javastudy; import java.util.HashMap; import java.util.Map; public class TestMap { public static void main(String [] args ){ Map<String, String> map = new HashMap<String, String>(); map.put(String.valueOf(System.nanoTime())+"a"

Map如何遍历key和value?

Map是一个集合接口,提供的是键值对的映射关系存储.它和其他集合不一样,没有继承自Collection接口,而是直接继承自Java.lang.Object.它包含着两个实现类,HashMap和TreeMap. 以下将运用两个简单的代码示例展示如何遍历Map集合的key和value 遍历KEY 1 Map<String, Object> map = new HashMap<>(); // 实例化map对象 2 map.put("name", "lay&q