Java-集合之Map的使用

Map

  • Map接口:内部存储的元素都是key–value组成的键值对,无序并且没有下标;通过key访问value,key不可重复

  • Map集合有 key 和value值,它们成对出现,成为对应的Entry 对象

  • key值 可以是任意类型,无序,不可重复,允许null值;用Set集合表示

  • value值 可以是任意类型,无序,可以重复,允许null值;用Collection集合表示

  • Map实现类

    • HashMap:Key允许null不允许重复,无序,线程不安全(动态数组+链表/红黑树)
    • TreeMap:Key不允许null不允许重复,无序,对键自动排序,要求作为键的对象必须实现Comparable接口(平衡二叉树)
怎么获取map集合中的key和value,有什么方式?

1、查找所有的key值: 调用keySet()方法

Map map = new HashMap();
Set keySet = map.keySet();
for(Object key : keySet){
    System.out.println("key:"+key+",value:"+map.get(key));
}

2、查找所有的value值:调用values()方法

Map map = new HashMap();
Collection valueSet = map.Values();
for(Object value : valueSet){
    System.out.println("value:"+map.get(key));
}

3、单个value值【根据key获取value值】: 调用get(key)方法。

4、 【1】查找所有的Entry值: 调用entrySet()方法;

​ 【2】遍历该Entry集合,执行 getKey() 或 getValue()

Set<Map.Entry<String,String>> entrySet = map.entrySet();
for(Entry<String,String> en : entrySet){
    String key = en.getKey();
    String value = en.getValue();
    System.out.println(key+","+value);
}

问题:key不相等则新元素插入到旧元素的后面,next怎么指向

HashMap
  • put往map里面存储元素(数组长度默认为16,负载因子0.75,即当长度为16*0.75=12时扩容,扩容两倍)
    • 根据key值进行判断hash,得到key的int hash值
    • hash & 数组长度->下标(用key的哈希值和数组长度做与运算,余数就是当前元素的下标)
    • 将这个元素存放到对应的下标
  • get获取map里面的元素
    • 根据key值进行判断hash,得到key的int hash值
    • hash & 数组长度->下标(用key的哈希值和数组长度做与运算,余数就是当前元素的下标)
    • 根据下标获取数组里面的元素
  • hash碰撞或者不同的hash值 与数组长度&运算:导致下标一样
    • 当发现相同的下标已经存储了元素,就根据equals判断key值是否相等
      • key相等则进行元素覆盖
      • key不相等则新元素占据旧元素的位置,新元素里面next指向旧元素(单链表)(jdk1.7是这样占据旧的位置)
      • key不相等则新元素插入到旧元素的后面,新元素里面next指向旧元素(单链表)
    • 变形
      • 添加元素:当链表长度超过8个元素,并且数组长度大于64,就将链表变形成红黑树进行存储
      • 移除元素:当移除只剩6个元素时,红黑树会自动变成链表

基本用法

package com.qianfeng.xqc.day0306;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * map存储的 键值对,key value的存放方式
 * 增:put(key,value);key不可重复 , value随便
 * 删:map.remove("1001");//根据key值删除
 * 查:get(key); //只能通过key值获取value值; 不能通过value值获取key
 * 改 : 不存在修改key; 如果key不一样,就代表是新增
 * @author 淳
 *
 */
public class DemoHashMap {

	public static void main(String[] args) {

		Map<String,String> map = new HashMap<String,String>();
		
		//增  put(key,value); key不可重复 , value随便
		map.put("1001", "张三");
		map.put("1002", "翠花");
		map.put("9999", "rose");
		map.put("6666", "jack");
		map.put(null,"什么都没有");
		
		System.out.println(map.size());
		
		//删
//		map.remove("1001");//根据key值删除
		map.remove("rose"); //移除失败; 因为没有key值rose
		
		System.out.println(map.size());
		
		//改 : 不存在修改key; 如果key不一样,就代表是新增;
		map.put("1001","李四"); //修改;将我们对应key里面的value进行修改;
		
		
		//查
		//1: 查一个  get(key); //只能通过key值获取value值; 不能通过value值获取key;
		String name = map.get("1001"); //如果没有这个key值,将会返回null
		System.out.println(name);
		
		//2: 遍历
		
		//2.1 获取所有的key值,通过key值去遍历
		Set<String> set = map.keySet();
		System.out.println(set.getClass());
		
		//set: 存放的咱们map所有的key值;
		for(String str : set) {
			
			//str : 代表我们每一次取出来的key值.
			//如何获取value值;
			System.out.println("map的key:" + str + ",map的value: " + map.get(str));
		}
		
		
		System.out.println("==============================");
		
		//2.2 只对map里面有哪些值感兴趣,不想知道key
		Collection<String> values = map.values();
		System.out.println(values.getClass());
		for(String str : values) {
			System.out.println(str);
		}
		
		
		System.out.println("++++++++++++++++++++++++++++++++++");
		//2.3 key和value同时拿到;  -> Entity(接口) -> Node(节点)
		Set<Entry<String, String>> entrySet = map.entrySet();
		
		for(Entry et : entrySet) { //每个et都是一个节点
			
			String key = (String) et.getKey();
			String value = (String) et.getValue();
			
			System.out.println("key:" + key + ",value:" + value);
		}
		
		
		System.out.println("正常运行");
	}

}
TreeMap
  • 无序但是一定会排序,所以一定要实现Comparable接口,或者自定义比较器

基本用法

package com.qianfeng.xqc.day0309;

import java.util.Collection;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

/**
 * map存储的 键值对,key value的存放方式
 * - TreeMap集合有 key 和value值,它们成对出现,成为对应的Entry 对象
 * - key值 可以是任意类型,无序,不可重复,不允许null值;用Set集合表示
 * - value值 可以是任意类型,无序,可以重复,允许null值;用Collection集合表示
 * 增:put(key,value);key不可重复 , value随便
 * 删:tree.remove("1001");//根据key值删除
 * 查:get(key); //只能通过key值获取value值; 不能通过value值获取key
 * 改 : 不存在修改key; 如果key不一样,就代表是新增
 * @author 淳
 *
 */
public class DemoTreeMap {

	public static void main(String[] args) {

		//实例化了一个TreeMap对象
		TreeMap<Integer, String> tree = new TreeMap<Integer, String>();
				
//		 * 增:put(key,value);key不可重复 , value随便
		tree.put(1001, "张三");
		tree.put(1002, "李四");
		tree.put(6666, "jack");
		tree.put(9999, "rose");
//		tree.put(null, "nothing");//TreeMap的key不允许null
		
//		 * 删:tree.remove("1001");//根据key值删除
		tree.remove(1001);
		
//		 * 改 : 不存在修改key; 如果key不一样,就代表是新增,key重复就是覆盖
		tree.put(1002, "王二麻子");
		
		
//		 * 查:get(key); //只能通过key值获取value值; 不能通过value值获取key
		System.out.println(tree.get(9999));
		
		//查询; 1: 增强循环 2: 迭代器
		System.out.println("--------key遍历----------");
		//获取所有的key值,通过key值去遍历
		Set<Integer> keySet = tree.keySet();
		for(Integer i : keySet) {
			System.out.println(i);
		}
		
		System.out.println("-------value遍历-------");
		//获取所有的value值
		Collection<String> values = tree.values();
		for(String s : values) {
			System.out.println(s);
		}
		
		System.out.println("-------key-value遍历-------");
		//通过Entity(接口)的Node(节点)获取map集合中的key和value
		Set<Entry<Integer, String>> entrySet = tree.entrySet();
		for(Entry<Integer, String> et : entrySet) {
			System.out.println("key:" + et.getKey() + ",value:" + et.getValue());
		}			
	}
}

判断重复:实现Comparable接口或自定义比较器

package com.qianfeng.xqc.day0309;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

/** 
 * TreeMap 会进行排序,所以除了判断重复,一定要进行 顺序的比较和排列;
 * TreeMap 需要自己去定义比较的方法
 * @author 淳
 *
 */
public class TestTreeMapComparable {

	public static void main(String[] args) {
			
		//TreeMap一定要进行比较,TreeMap指定比较器,在Person中实现Comparable接口
//		TreeMap<Person,String> tree = new TreeMap<Person,String>();
		
		//自定义比较器实现Comparator接口,重写compare方法
		TreeMap<Person,String> tree = new TreeMap<Person,String>(new MyCompator());
		
		//新建多个人对象
		Person p1 = new Person("xqc", 23);
		Person p2 = new Person("tom", 23);
		Person p3 = new Person("jim", 23);
		Person p4 = new Person("xqc", 23);
		Person p5 = new Person("xqc", 24);
		Person p6 = new Person("xx", 23);
		Person p7 = new Person("tom", 43);
		
		//将这些Person对象放入Map集合中
		tree.put(p1,"a");
		tree.put(p2,"c");
		tree.put(p3,"b");
		tree.put(p4,"d");
		tree.put(p5,"d");
		tree.put(p6,"d");
		tree.put(p7,"d");
		
		System.out.println(tree.size());
		
		Set<Person> keySet = tree.keySet();
		
		for(Iterator<Person> iterator = keySet.iterator();iterator.hasNext();) {
			Person p = iterator.next();
			System.out.println(p + "," + tree.get(p));
		}
			
//		test();
	}
	
	public static void test() {
		TreeMap<String,Integer> Map = new TreeMap<String,Integer>();
		//String不用去实现比较接口,String自己内部实现了Comparable
		Map.put("b",1);
		Map.put("a",2);
		Map.put("c",3);
		Map.put("e",4);
		Map.put("s",5);
		
		Set<Entry<String, Integer>> entrySet = Map.entrySet();
		for(Entry<String, Integer> et : entrySet) {
			System.out.println("key:" + et.getKey() + ",value:" + et.getValue());
		}
		
	}
}

/**
 * 自定义比较器实现Comparator接口,重写compare方法
 * 姓名年龄都相同才是同一个元素,所以先按姓名排序,姓名一样在按照年龄排序
 * @author 淳
 *
 */
class MyCompator implements Comparator<Person>{

	//1 根据姓名判断是否同一个元素
	//2 根据年龄判断
	//姓名年龄都相同才是同一个元素,所以先按姓名排序,姓名一样在按照年龄排序
	
	@Override
	public int compare(Person o1, Person o2) {
		
		if(o1.getName().compareTo(o2.getName()) == 0) {//姓名相同,按年龄排序
			return o1.getAge() - o2.getAge();
		}
		
		//名字不一样
		return o1.getName().compareTo(o2.getName());
	}
	
}


class Person implements Comparable<Person>{
	private String name;
	private Integer age;
	public Person(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void MapName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void MapAge(Integer age) {
		this.age = age;
	}
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	//TreeMap去进行比较,就是调用compareTo这个方法去比较;默认返回的都是0 ,代表相等;
	@Override
	public int compareTo(Person o) {
		
		//根据姓名判断两个元素是否相等
		//String如何去比较:直接使用字符串自己写好的比较规则,去对name进行比较;
		return this.name.compareTo(o.name);
		
		//根据年龄来比较呢?
//		return this.age - other.age;
		
		//-1 比原来的元素小   0  相等   1 比原来的元素大
//		return 0;
	}
	
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值