菜鸡在学JAVA坎坷路day.17(容器3:Map加强版,Set)

本文介绍了自定义实现Map和Set的过程,包括Map的数组加链表结构以及Set如何利用Map实现元素唯一性。深入探讨了hashCode方法的重要性,并对比了HashMap与HashSet的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Map加强版;(增加检索的效率)

List  是有序可重复;

我们使用Map的时候一般这样写: Map a =new HashMap();//一般都是这样写   接口加一个实现类

Map接口的一个实现类  HashMap 他还有一个实现类就是HashTable  前者是线程安全的(就和StringBuilder,StringBuffer;ArrayList,Vector)他们类似 

set   无序不可重复   新对象不能equals老的对象;

package TestMap;

import java.util.LinkedList;

/**
 * 根据Map来实现自己的Map  上一个Map效率太低  这次我们改进
 * @author Wang
 * 说明  : Map的底层实现是根据  数组加链表实现的  下面我们来模仿一下
 */

public class MyMap002 {
	
	LinkedList[] array = new LinkedList[9999]; //建立一个链表数组;  在链表的里面存放键值对
	int size;
	
	
	public void put(Object key,Object value) {
		
		Map01 e = new Map01(key,value); //Map01中的存放键值对的类
		
		int hash = key.hashCode();//这个方法的作用是  根据key这个对象的地址来生成一个hashcode码   每个对象的地址不同会生成不同码
		hash = hash<0?-hash:hash;//这个地方有一个问题就是hashCode可能是一个负数  用这一句来避免  判断他是不是负数是负数的话就取相反数,不是的话  就不用改变;
		
		int a = hash % array.length;//这样保证hash的值e都在 数组的索引范围内
		if(array[a] == null) {//说明数组的这个位置还没存放链表  他将会是第一个
			LinkedList list = new LinkedList();//建立一个新的链表对象准备放到数组里面
			array[a] = list;
			list.add(e);//将键值对放到list里面
			size++;
			
		}else {//在这里要考虑Map的键相同的时候  value要被覆盖  所以要遍历里面的list的key是否和传入的key相同  
			LinkedList list = array[a];//去除array[a]里面现有的链表  进行遍历
			
			for(int i=0; i<list.size();i++) {
				
				Map01 e2 = (Map01)list.get(i);//取出来都是Object类型的了   要强制转换
				if(e2.key.equals(key)){
					e2.value =value;//键相同就直接覆盖
					return ;//要是覆盖以后就跳出这个put方法
				}
				
			}
			
			array[a].add(e);//直接在array【a】这个链表后面加了一个e
			size++;
		}
		
	
	}
	
	
	public Object get(Object key) {//通过key来查找  就先通过key的地址来确定是哪一个数组  然后遍历链表里面的key就行了
		
		int hash = key.hashCode();
		int a = hash % array.length;
		
		
		LinkedList list = array[a];
		for(int i=0;i<list.size();i++) {
			Map01 e =(Map01)list.get(i);
			if(e.key == key) {
				return e.value;
			}
		}
		return null;
		
	}
	
	
	public int size() {
		return size;
	}
	
	
	public static void main(String[] args) {
		MyMap002 map1 = new MyMap002();
		
		map1.put("wang", 1);
		map1.put("wang1", 2);
		map1.put("wang2", 3);
		map1.put("wang3", 4);
		map1.put("wang", "哈士奇");
		
		System.out.println(map1.get("wang"));
		System.out.println(map1.size());
	}
	
}

2.set(一个继承Collection接口)

他是无序不可重复(List是有序可重复);

我们用的最多的就是HashSet(他的底层实现是通过Map)(set里面的元素其实就是Map里面的key);

package TestSet;

import java.util.HashSet;
import java.util.Set;

/**
 * Set的基本方法   Hash的底层实现用的是Map  他的元素就是Map的Key所以不可重复
 * @author Wang
 *
 */

public class testSet01 {
	public static void main(String[] args) {
		Set set = new HashSet();
		set.add("aaaa");
		set.add("bbbb");
		set.add(new String("aaaa"));//重复了  会覆盖
		
		System.out.println(set.size());
		set.remove("aaaa");
	}
}

3.MySet

package TestSet;

import java.util.HashMap;

/**
 * 自己写一个简单的Set
 * @author Wang
 *
 */

public class MySet {
	HashMap map;
	private static final Object PRESENT = new Object();//这个用于map的Value(无意义)   HashSet的元素是Map的keys
	
	
	public MySet() {
		map = new HashMap();
	}
	
	public int size() {
		return map.size();
	}
	
	public void add(Object o) {
		map.put(o,PRESENT);//Set的不可重复性就利用了这个
	}
	
	public static void main(String[] args) {
		MySet a = new MySet();
		
		a.add("aaa");
		a.add("aaa");//重复的会自动覆盖
		a.add("ccc");
		
		System.out.println(a.size());
	}
	
}


注意:

hashCode():两个内容相同的对象一定有相同的hashCodes,但是相同的hashcodes相同不一定对象相等;(可以这样说如果两个对象的equals为true  那么他们的hashcode()一定相等,反之则不然);

hashCode()是可以重写[hashcode()和equals一般同时重写   可以使用source生成;

容器的三大接口 : list,set,map用的都很多;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值