有关Map集合(双列集合)

在现实生活中每个人都有唯一一个身份证号,通过身份证号可以查询到这个人的信息,这两者是一对一的关系。在应用程序中,如果想存储这种具有对应关系的数据,则需要使用JDK中提供的Map接口。Map接口时一个双列集合,它的每一个元素都包含一个键对象Key和一个值对象Value,键和值对象之间存在一种对应关系,称为映射。从Map集合中访问元素时,只要指定额Key就可以得到相应的Value。

Map集合中重要的几个接口和类如下:
SortedMap接口:进一步提供关于键的总体排序 的 Map。该映射是根据其键的自然顺序进行排序的,或者根据通常在创建有序映射时提供的 Comparator 进行排序。
NavigableMap接口:(SortedMap的子接口)扩展的 SortedMap,具有了针对给定搜索目标返回最接近匹配项的导航方法。
AbstractMap抽象类:此类提供 Map 接口的骨干实现,以最大限度地减少实现此接口所需的工作。
WeakHashMap类:(AbstractMap的子类)以弱键实现的基于哈希表的Map,即在WeakHashMap中,当某个键不再正藏使用的时,将自动移除其条目的键,其映射的存在并不阻止垃圾回收器对该键的丢弃。这就使得该键成为可终止的,被终止,然后被回收。
ConcurrentMap类:(AbstractMap的子类)支持获取的完全并发和所期望可调整的并发的哈希表,是线程安全的。
HashMap类:(AbstractMap的子类)提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是不保证该顺序恒久不变。
TreeMap类:(AbstractMap的子类)基于红黑树(Red——Black Tree)的NavigableMap实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的ComparaTo进行排序,具体取决于使用的构造方法。
在这里插入图片描述
一、HashMap类相关的操作
(1)通过put(Object Key,Object Value)方法向集合中加入元素,通过get(Object Key)方法获取与键值对应的值;需要注意的是:键值必须是唯一的,不能重复。如果存储了相同的键,后面存储的值后覆盖掉原有的值,即键相同,值覆盖
举例:

public void a() {
		Map<String, Object> map = new HashMap<>();
		
		map.put("1", "田田");
		map.put("2", "蒸弦");
		map.put("3", "无理");
		map.put("3", "李尔");
		
		System.out.println(map);
		System.out.println(map.get("1"));//取出键1对应的值
		System.out.println(map.get("2"));//取出键2对应的值
	}
	
	运行结果:
	{1=田田, 2=蒸弦, 3=李尔}
	田田
    蒸弦
	由结果可得:键值为“3”的重复了,后面的值“李尔”替换了原有的值“无理”

(2)遍历得到Map中所有的键值对

	①第一种方法:首先调用Map对象的keySet()方法,获得存储Map中所有的键的Set集合,
	然后通过Iterator迭代Set集合的每一个键,最后通过通过调用get(Object key)方法,
	根据键获取对应的值。
	public void b() {
		Map<String, Object> map = new HashMap<>();

		map.put("1", "田田");
		map.put("2", "蒸弦");
		map.put("3", "无理");
		map.put("4", "李尔");
		
		Set keySet = map.keySet();//获取键的集合
		Iterator it = keySet.iterator();//迭代键的集合
		while(it.hasNext()) {
			Object key = it.next();
			Object value = map.get(key);//获取每个键对应的值
			System.out.println(key+":"+value);
		}
	}
	运行结果:
   1:田田
   2:蒸弦
   3:无理
   4:李尔


②第二种方法:
首先调用Map对象的entrySet()方法获得存储在Map中所有映射的Set集合,这个集合中存放
了Map.Entry类型的元素(Entry是Map接口内部类),每个Map.Entry对象代表Map中的一个
键值对,然后迭代Set集合,获得每一个映射对象,并分别调用映射对象的getKey()和
getValue()方法获取键和值。

public void c() {
		Map<String, Object> map = new HashMap<>();
		
		map.put("1", "田田");
		map.put("2", "蒸弦");
		map.put("3", "无理");
		map.put("4", "李尔");
		Set enterySet = map.entrySet();
		Iterator it  = enterySet.iterator();
		
		while(it.hasNext()) {
			Map.Entry<String, Object> entry =(Map.Entry<String, Object>)(it.next());
			Object key = entry.getKey();
			Object vlaue = entry.getValue();
			System.out.println(key+":"+vlaue);
		}
	}
	运行结果:
	1:田田
    2:蒸弦
    3:无理
    4:李尔

二、TreeMap类的相关操作
(1)通过put(Object Key,Object Value)方法向集合中加入元素,通过get(Object Key)方法获取与键值对应的值;需要注意的是:键值必须是唯一的,不能重复。如果存储了相同的键,后面存储的值后覆盖掉原有的值,即键相同,值覆盖。除此之外,TreeMap集合,取出的元素是自动进行了排序的,是因为实现了Comparable接口,里面的comparaTo()方法会默认按照自然顺序进行排序。
例:

public void demo() {
		Map<String, Object> map = new TreeMap<String, Object>();
		map.put("3", "离儿");
		map.put("1", "徐离");
		map.put("2", "高键");
		map.put("3", "菲菲");
		System.out.println(map);
	}
	运行结果:
	{1=徐离, 2=高键, 3=菲菲}
	可以看到,结果是排了序的

(2)遍历得到Map中所有的键值对与HashMap方法相同
(3)对于自定义类的集合,需要实现Comparable接口并重写里面的comparaTo()方法,设定排序规则,如果不实现,会出现异常。

public void demo() {
		Map<A,String > map = new TreeMap<>();
		
		A a1 = new A(3, "lala", 20);
		A a2 = new A(2,"yaya",30);
		A a3 = new A(1, "lulu", 19);
		
		map.put(a3,"露露");
		map.put(a2,"丫丫");
		map.put(a1,"啦啦");
		
		System.out.println(map);
		
	}
	运行结果:
	{A [id=1, name=lulu, age=19, getId()=]=露露,
	 A [id=2, name=yaya, age=30, getId()=]=丫丫,
	 A [id=3, name=lala, age=20, getId()=]=啦啦}
	 可以看到结果是按照id排序的
自定义类
public class A implements Comparable<A>{//实现Comparable接口

	private Integer id;
	private String name;
	private Integer age;
	
	
	public A(Integer id, String name, Integer age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}

	public int hashCode() {
		return id;
	}

	public String toString() {
		return "A [id=" + id + ", name=" + name + ", age=" + age + ", getId()=]";
	}

	public boolean equals(Object obj) {
		A a = (A)obj;
		return this.getId()==a.getId();
	}

	public int compareTo(A o) {//重写compareTo()方法,按照id来排序
		return this.getId()-o.getId();
	}
}

三、有关HashMap、TreeMap键值是否可以为null的举例

public class Demo03 {

	public void a() {

		Map<Integer, Object> map1 = new HashMap<>();
		
		String a1= "A2";
		map1.put(559, "A1");
		map1.put(471, a1);
		map1.put(342, "A3");
		map1.put(768, "A4");
		map1.put(229, "A5");
		map1.put(878, "A6");
		
		System.out.println(map1);
		System.out.println("----------------------------------");
		map1.remove(342);
		a1 = "AAA";
		map1.put(648, null);
		map1.put(null, null);
		map1.put(null, "zhensghuang");
		System.out.println(map1);
	}

    public static void main(String [] args){
          new Demo01().a();
    }
}

运行结果:
{768=A4, 229=A5, 342=A3, 471=A2, 878=A6, 559=A1}
---------------------------------------------------------------
{768=A4, null=zhensghuang, 229=A5, 471=A2, 648=null, 878=A6, 559=A1}
根据运行结果知:
HashMap的键为null和值为null都可以
(这里没有输出null=null,这对键值,是因为后面添加的键值null=zhengshuang,覆盖
了前面的null=null)
但是注意:TreeMap的j值可以为null,键能否为null分情况而言;
当没有实现Comparator接口时,TreeMap的键是不能为null的,会抛出java.lang.NullPointerException异常;
当实现Comparator接口时,并重写里面的compare()方法未对键为null进行判断,则抛出java.lang.NullPointerException异常
当实现Comparator接口时,并重写里面的compare()方法并对键为null进行判断,则可以成功存入
例如:下面是 键值为null时可以成功存入的情况
public void demo() {
Map<Integer, Object> map = new TreeMap<>(new Comparator<Integer>() {
			public int compare(Integer o1, Integer o2) {
				if(o1 ==null) {
					return 1;
				}else {
					return o2-o1;
				}
			}
		
		});
		
		map.put(2, null);
		map.put(null, 2);
		map.put(null,null);
		System.out.println(map);
	}
	运行结果:
	{2=null, null=2, null=null}

四、介绍有关集合的另外一种特殊情况:集合中存放的对象及对象内容发生改变,集合怎样变化

public void demo1() {
		List<String> list = new ArrayList<>();
		Set<String> set = new HashSet<>();
		Map<Object,String> map = new HashMap<>();
		
		String str = new String("abc");
		list.add(str);
		set.add(str);
		map.put(6,str);
		System.out.println(list);
		System.out.println(set);
		System.out.println(map);
		System.out.println("---------------------");
		str = new String("aaa");
		System.out.println(list);
		System.out.println(set);
		System.out.println(map);
	}
	
运行结果
[abc]
[abc]
{6=abc}
---------------------
[abc]
[abc]
{6=abc}

demo1()方法是对象的指向发生改变,由运行结果可知集合并未发生改变

public void demo2() {
		List<A> list = new ArrayList<>();
		Set<A> set = new HashSet<>();
		Map<Integer,A> map = new HashMap<>();
		
		A a = new A(1, "田菲", 20);
		list.add(a);
		set.add(a);
		map.put(1, a);
		System.out.println(list);
		System.out.println(set);
		System.out.println(map);
		System.out.println("------------------------------");
		
		a.setName("李盾");
		System.out.println(list);
		System.out.println(set);
		System.out.println(map);
	}
	
运行结果:
[A [id=1, name=田菲, age=20, getId()=]]
[A [id=1, name=田菲, age=20, getId()=]]
{1=A [id=1, name=田菲, age=20, getId()=]}
----------------------------------------------
[A [id=1, name=李盾, age=20, getId()=]]
[A [id=1, name=李盾, age=20, getId()=]]
{1=A [id=1, name=李盾, age=20, getId()=]}

demo2()方法存放的是对象的应用,可以看到对象的内容发生变化,集合也改变了

由两个方法对比可以总结出:
若是对象的指向发生改变,集合不改变;
若集合中存放的是对象的引用类型,如果对象的内容发生改变,对象的内存地址会发生改变,集合也就会改变。

两种情况结合的例子:

public void d() {
		Map<Integer, A> map = new HashMap<>();
		A a1 = new A(1, "张三", 29);
		A a2 = new A(2,"田灿",20);
		A a3 = new A(3,"旭样",44);
		map.put(7, a1);
		map.put(34, a2);
		System.out.println(map);
		a2.setName("田菲");//改变
		System.out.println(map);
		a2 = null;//这种方法并没有改变集合的内容,只是指向改变所以集合不改变
		System.out.println(map);
		a2 = a3;//不改变
		System.out.println(map);
	}
运行结果:
{34=A [id=2, name=田灿, age=20, getId()=], 7=A [id=1, name=张三, age=29, getId()=]}
{34=A [id=2, name=田菲, age=20, getId()=], 7=A [id=1, name=张三, age=29, getId()=]}
{34=A [id=2, name=田菲, age=20, getId()=], 7=A [id=1, name=张三, age=29, getId()=]}
{34=A [id=2, name=田菲, age=20, getId()=], 7=A [id=1, name=张三, age=29, getId()=]}
这里是A类的代码
public class A implements Comparable<A>{

	private Integer id;
	private String name;
	private Integer age;
	
	
	public A(Integer id, String name, Integer age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public int hashCode() {
		
		return id;
	}

	@Override
	public String toString() {
		return "A [id=" + id + ", name=" + name + ", age=" + age + ", getId()=]";
	}

	public boolean equals(Object obj) {
		A a = (A)obj;
		return this.getId()==a.getId();
	}

	public int compareTo(A o) {
		return this.getId()-o.getId();
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值