Java基础(6)--容器(2)常用的map接口实现类

1. map接口简介

  • 实现map接口的类常用来存储键(key)-值(value)对;
  • Map的底层实现是数组+链表(在数组中添加链表,用以减少遍历);
  • 可以先定义一个链表数组(意思就是 每一个数组元素都是一个链表);
  • map接口的实现类有HashMap、TreeMap和HashTable等;
  • map类中存储的值由键来标识,就像是数据库的主键一样,不能重复;
  • map中一般都是通过key寻找另一个对象;
  • HashMap的效率高,但是安全性较低;HashTable效率低,但是安全度高;主要使用就是这两个类;HashTable的使用和HashMap相似;

2. HashMap中的重要方法说明:

以下就是所有重要的HashMap中的方法,

public class TestMap {
	public static void main(String[] args) {
		
		Map map1 = new HashMap();
		map1.put("1", "545");
		map1.put("455", "sdeed");
		
		
		Map map = new HashMap();
		map.put("dxs", "无奈");
		map.put(new Integer(124), "测试");
		map.put("dd","张的收");
		map.put("测试remove",new Text(12) );
		map.putAll(map1);//将所有的map1函数全部放到map里面;
//		map.clear();将所有的元素全部删除;
		//这里之所以需要进行转型是因为get出来的值是Object类型
		//由于一般都要和泛型同时使用,没用泛型的话,默认就是object返回类型;
		Text t = (Text)map.get("测试remove"); //将这个得到的对象赋值给t;
		
		map.containsKey("dxs");//这是一个boolean类型的方法;用来查看对象里面是否有这个key值;
		map.containsValue("sdf");//这是用来检测是否含有这个value值,同样也是boolean类型;
		int x = map.size();//测试map的长度;这里结果是4
		map.remove("测试remove");//观察remove是直接删除还是将数值移除出去,却并不删掉;
		int y = map.size();//这里的答案是3,因为程序运行的顺序决定了结果;在这段代码前面移除了一个元素;
		
		
		System.out.println(t.age);
		System.out.println(y);
		System.out.println(x);
		System.out.println(map.get(124));
	}
}

class Text{
	public int age;
	public  Text(int age) {
		this.age  = age;
	}
}

如果两个元素的键值(key)相同,那么在get时,会获取后一个元素的value;
准确点说就是map是通过键来取值,所以如果有两个键相同的值,那么后一个值就会覆盖前一个值;

下面程序是对map的基础存储架构进行一个更深层的理解;

public class MyMap {
	
	private int size;//定义一个长度
	MyLinkedList[] arr = new MyLinkedList[999]; //定义一个数组为999的大小,每一个元素都是一条链子;
	
	public int size() {//返回一个长度方法
		return size;
	}
	
	public void put(Object key,Object value) {//一个get方法
		//使用hashcode()函数求值,并取数组的长度的余数;
		int a = key.hashCode()%arr.length;
		//这里定义一个Entry类,用来存两个数;
		Entry e = new Entry(key,value);
		//定义一个链条
		MyLinkedList list = new MyLinkedList();
		//判断这个数组的元素是否为空,这里的每个数组元素都是一条链;
		if(arr[a]==null) {
//			通过list添加键值
			list.add(e);
//			将链条重新赋给arr数组,毕竟存起来的是数组
			arr[a] = list ;
//			在这里计算size
			size++;
//			以下是arr[a]数组非空的情况下,要判断是否要覆盖
		}else {
//			原先中的arr[a]链条赋给list;
			list = arr[a];
//			进行遍历list
			for(int i=0;i<list.size();i++) {
//				取出list中的值,将其存入Entry类
				Entry en =  (Entry) list.get(i);
//               进行判断,链子中是否有相同的key,如果有就把最新的值覆盖掉之前的值;
				if(en.key.equals(key)) {
					en.value=value;//将值进行简单的覆盖即可
					break;//覆盖后退出
				}
				list.add(e);//如果没有相等的值,就直接在后面使用add()函数填入即可;
				arr[a] = list;//因为实际存储的还是arr数组,所以要将链条赋值给数组;
			}
		}
	}
	//一个get方法
	public Object get(Object key)  {
//		一样的先求取哈希值
		int a = key.hashCode()%arr.length;//求取哈希值
//		进行反判断,arr数组是否为空
		if(arr[a]!=null) {
			MyLinkedList list =arr[a];
//			进行遍历,查询到已有key值和目前查询key值是否相等;
			for(int i=0;i<list.size();i++) {
				Entry e = (Entry) list.get(i);
				if(e.key.equals(key)) {
					return e.value;//如果相等,就将值取出;
				}
			}
		}
		return null;//否则回复null
	}
	
	public static void main(String[] args) {
		MyMap mp = new MyMap();
		mp.put("123",45);
		mp.put(new Integer(456), "神");
		System.out.println(mp.size());
	}
}


//定义一个类用来专门存放键值对
 class Entry{
	public Object value;
	public Object key;
	
	public Entry(Object value, Object key) {//一个构造方法;用来存取键值对;
		super();
		this.value = value;
		this.key = key;
	}
}

各个类的结合可能有错,但是基本思维应该是没有错的;

3. TreeMap介绍和使用

  • TreeMap是典型红黑二叉树的实现;
  • TreeMap和HashMap实现了同样的接口Map,但是HashMap的效率要高于TreeMap,一般如果Map需要排序时,就会使用TreeMap;
 public class MyTreeMap {
	public static void main(String[] args) {
		Map<Integer,String> treemap = new TreeMap<Integer, String>();
		treemap.put(1,"dxs");//放入元素;
		treemap.put(3, "莫须有");
		treemap.put(2,"神秘的天");

		for(Integer key:treemap.keySet()) {//用foreach直接输出;
			System.out.println(key+"-"+treemap.get(key));
		}
	}
}

最后的结果输出时是按key值的顺序输出的;

自己写的类使用TreeMap进行排序

红黑二叉树就不过多赘述,等我学了再说;
自己写一个简单的类,然后使用TreeMap进行排序;

public class MyTreeMap {
	public static void main(String[] args) {
		Map<textclass,String> treemap = new TreeMap<textclass, String>();
		treemap.put(new textclass(1, 100000), "dxs");
		treemap.put(new textclass(3, 500), "神秘的天");
		treemap.put(new textclass(2, 6000), "神天");
		treemap.put(new textclass(2, 6000), "无意");//仅仅是为了测试是否还是满足map特性,key不重复,结果是满足
		
		for(textclass key:treemap.keySet()) {//通过keySet方法可以得到这个类的Key值:然后赋值给key变量进行遍历;
			System.out.println(key+"-"+treemap.get(key));
		}
	}
}


class textclass implements Comparable<textclass>{
	public int id;
	public int salary;
	public textclass(int id, int salary) {
		super();
		this.id = id;
		this.salary = salary;
	}
	
	@Override
	public String toString() {//简单重写一个toString方法用于输出完整的key值;否则只会输出对象地址,无法输出准确的key;
		return ""+id+"-"+salary;
	}
	
	@Override
	public int compareTo(textclass o) {
		/*一下是该方法的介绍
		 * Compares this object with the specified object for order. Returns a negative
		 * integer, zero, or a positive integer as this object is less than, equal to,
		 * or greater than the specified object.
		 * 
	     * 意思大概就是说CompareTo主要用于对象的排序,返回一个负数,0,或者正整数,看做是小于,等于和大于,对于那些具体的对象来说;
	     * 他这里进行比较的是以当前对象,也就是this为主,和他进行比较的对象称之为具体对象,也就是o所代表的对象;
	     * 如果this对象的属性大于o对象的属性就返回1;小于就返回-1,否则就返回0;
		 */
		if(this.id<o.id) {
			return -1;
		}else if(this.id>o.id) {
			return 1;
		}else if(this.salary<o.salary) {
			return -1;
		}else if(this.salary>o.salary){
			return 1;
		}else {
			return 0;
		}
	}
}

下图是程序运行的结果;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神秘的天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值