Map接口
前情概要:
存放Set集合元素的容器,必须要重写hashCode( )和equals( )方法,这样才可以保证Set集合中的元素不会重复。
凡是跟集合这块,要你存的话,equals( )方法是一定要写的;如果是跟Map或Set相关的话,除了写equals( )方法外,还要写hashCode( )方法。
上图中实线表示继承;虚线表示实现。
一个ksy-value对就是一个entry;所有的entry是一个set。
一、Map常用的集合元素:
1、Map集合的实现定义与在Map集合中的添加、删除操作:
package com.atguigu.Map00;
import java.util.HashMap;
import java.util.Map;
/*
* Collection接口
*
* Map接口
* |------HashMap:Map的主要实现类
* |------LinkedHashMap:
* |------TreeMap:
* |------HashTable
* |------Properties
* */
import org.junit.Test;
/*
* HashMap:
* 1、key是用Set来存放的,不可重复。value是用Collection来存放的,可重复;
*一个key-value对,是一个Entry。所有的Entry是用Set存放的,也是不可重复的。
* 2、向HashMap中添加元素时,会调用key所在类的equals()方法,判断两个key是否相同。
* 若相同则只能添加进后添加的那个元素。
* */
public class TestMap {
@Test
public void testMap1() {
Map map=new HashMap(); //1、Object put(Object key,Object value):向Map中添加一个元素
// map.put(key, value);
map.put("AA", 213); //正是因为key是不可重复的所有Entry才不可重复。
map.put("BB", 456);
map.put("BB", 456);
map.put(123, "CC");
map.put(null, null);
map.put(new Person("DD",23), 89);//put的两个Person实体类对象添加成功一个,因为key值不能相等。
map.put(new Person("DD",23), 98);
System.out.println(map.size());//结果为:4(因为put()里添加了一个key值重复的,只能算一个。)
System.out.println(map);
/*
* 结果:
5
{AA=213, BB=456, null=null, 123=CC, com.atguigu.Map00.Person@14c8c=98}
*/
map.remove("AA");
System.out.println(map.size());
System.out.println(map);
// map.clear(); //clear:清空Map集合
System.out.println(map.get(123));//get:输出key值为123对应的value值;如果没有此key则返回null。
}
}
2、元视图操作的方法:
//遍历Map集合中的key值用”某某.keySet()”
//遍历Map集合中的value值用”某某.values()”
//遍历Map集合中的key-value对用”某某.entrySet()”
Map map=new HashMap();
//1、遍历key集(用".keySet"):输出的结果与添加进HashMap的顺序不同。
Set set=map.keySet();
for(Object obj:set) {
System.out.println(obj);
}
//2、遍历value集:用".values"
Collection values=map.values();
Iterator i=values.iterator();
while(i.hasNext()) {
System.out.println(i.next());
}
//3、如何遍历key-value对
// 方式一:
Set set1=map.keySet();
for(Object obj:set1) {//通过key找相应的value值
System.out.println(obj+"------>"+map.get(obj));
}
// 方式二:
Set set2=map.entrySet();
for(Object obj:set2) {
Map.Entry entry=(Map.Entry)obj;//创建一个Map.Entry类型的。
// System.out.println(entry.getKey()+"------>"+entry.getValue());
System.out.println(entry);
}
①、代码例题演示:
public class TestMap {
/*
* 如何遍历Map
* Set keySet()
* Collection values()
* Set entrySet()
* */
@Test
public void testMap2() {
Map map=new HashMap();
map.put("AA", 213); //正是因为key是不可重复的所有Entry才不可重复。
map.put("BB", 456);
map.put(123, "CC");
map.put(null, null);
map.put(new Person("DD",23), 89);
//1、遍历key集(用".keySet"):输出的结果与添加进HashMap的顺序不同。
Set set=map.keySet();
for(Object obj:set) {
System.out.println(obj);
}System.out.println(" ****** ");
//2、遍历value集:用".values"
Collection values=map.values();
Iterator i=values.iterator();
while(i.hasNext()) {
System.out.println(i.next());
}
//3、如何遍历key-value对
// 方式一:
Set set1=map.keySet();
for(Object obj:set1) {//通过key找相应的value值
System.out.println(obj+"------>"+map.get(obj));
}
// 方式二:
Set set2=map.entrySet();
for(Object obj:set2) {
Map.Entry entry=(Map.Entry)obj;//创建一个Map.Entry类型的。
// System.out.println(entry.getKey()+"------>"+entry.getValue());
System.out.println(entry);
}
}
}
二、LinkedHashMap的使用:
LinkedHashMap:使用链表维护添加进Map中的顺序。故遍历Map时,是按照添加的顺序遍历的。
public class TestMap {
/*
* LinkedHashMap:使用链表维护添加进Map中的顺序。故遍历Map时,是按照添加的顺序遍历的。
* */
@Test
public void testLinkedHashMap() {
Map map=new LinkedHashMap();
map.put("AA ", 213);
map.put("123", 34);
map.put(456, 22);
map.put(new Person("MM",23), 80);
Set set=map.keySet();
for(Object obj:set) {
System.out.println(obj+"------>"+map.get(obj));
}
}
}
三、TreeMap的使用:
TreeMap:按照添加进Map中的元素的key的指定属性进行排序。 要求:key必须是同一个类对象。(自然排序 & 定制排序)
①、定制排序与自然自然排序的代码解析:
public class TestMap {
//|------TreeMap:按照添加进Map中的元素的key的指定属性进行排序。 要求:key必须是同一个类对象。
//定制排序
@Test
public void testTreeMap2() {
Comparator com=new Comparator() {
@Override //实现排序的方式
public int compare(Object o1, Object o2) {
if(o1 instanceof Customer && o2 instanceof Customer) {
Customer c1=(Customer)o1;
Customer c2=(Customer)o2;
int i=c1.getId().compareTo(c2.getId());
if(i==0) {
return c1.getName().compareTo(c2.getName());
}
return i;
}
return 0;
}
};
Map map=new TreeMap();
map.put(new Person("AA",23), 80);
map.put(new Person("MM",23), 70);
map.put(new Person("CC",13), 80);
map.put(new Person("BB",43), 60);
Set set=map.keySet();
for(Object obj:set) {
System.out.println(obj+"------>"+map.get(obj));
}
}
//自然排序
@Test
public void testTreeMap() {
Map map=new TreeMap();
map.put(new Person("AA",23), 80);
map.put(new Person("MM",22), 70);
map.put(new Person("CC",13), 80);
map.put(new Person("BB",43), 60);
Set set=map.keySet();
for(Object obj:set) {
System.out.println(obj+"------>"+map.get(obj));
}
}
四、Map实现类之4 : HashTable;HashTable的子类Properties的使用:
1、使用Properties处理属性文件(讲的是输出属性文件中key对应的value属性值):
①、Eclipse中在java project中右击 à new à file à命名一个文件名 à点击确定后在新建的文件里写key与value,即键值对。
2、关于properties的代码解析:
①、jdbc.properties文件
文件的内部写法如下:
user=name
password=123
②、代码实现:
public class TestMap {
/*
* 使用Properties处理属性文件(讲的是输出属性文件中key对应的value属性值)
* */
@Test
public void testProperties() throws FileNotFoundException, IOException{
Properties pros=new Properties();
pros.load(new FileInputStream("jdbc.properties"));//到此为止已经可以用load载入"jdbc.properties"文件了
String user=pros.getProperty("user");//获取属性文件"jdbc.properties"中的数据
System.out.println(user); //将属性文件中的信息逮入进来
String pass=pros.getProperty("password");
System.out.println(pass);
}
}
以上所有代码的总合:
1、Person类:
package com.atguigu.Map00;
public class Person implements Comparable{
int id=1002;
private String name;
private Integer age;
//有参的构造方法
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() { //无参的构造方法
super();
}
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;
}
//自定义的函数
public void walk() {
System.out.println("人走路");
}
public void eat() {
System.out.println("人吃饭");
}
@Override //用于Set接口比较
public int hashCode() {//1、return age.hashCode()+name.hashCode();没有下述的健壮性好。
//2、建议直接用系统自动生成的。
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
// 3、return init++;//不建议这样用
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
//向TreeSet中添加Person类的对象时,依据此方法,确定按哪个属性排列。
@Override
public int compareTo(Object o) {
if(o instanceof Person) {
Person p=(Person)o;
// return this.name.compareTo(p.name);//此处是按照name属性进行排序的。
// return -this.age.compareTo(p.age);//加上负号表示由大到小
// return this.age.compareTo(p.age);//按照age进行排序(age是Integer类型的,Integer也实现了compareTo方法)。
// 自然排序:要求自定义类实现java.lang.Comparable接口并重写其compareTo(Object obj)方法
// 在此方法中,指明按照自定义类的哪个属性进行排序。
// 为了使相同的也能写进TreeSet像数据库一样,有一级排序,一级排序相同再二级排序
/*实现的是先按照age从小到大排,age相等按name排*/
int i=this.age.compareTo(p.age);
if(i==0) {//如果有age相等的则按名字排序
return this.name.compareTo(p.name);
}else {//如果age不等则按age排序
return i;
}
}
return 0;
}
}
2、Customer类:
package com.atguigu.Map00;
public class Customer {
private String name;
private int id;
//Getters & Setters方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
//构造器
public Customer(String name, int id) {
super();
this.name = name;
this.id = id;
}
//toString方法
@Override
public String toString() {
return "Customer [name=" + name + ", id=" + id + "]";
}
//hashCode & equals()方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
3、TestMap类:(所有Map相关的子接口及子接口的实现类);此类由多个单元测试组成。
package com.atguigu.Map00;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
/*
* Collection接口
*
* Map接口
* |------HashMap:Map的主要实现类
* |------LinkedHashMap:
* |------TreeMap:
* |------HashTable
* |------Properties
* */
import org.junit.Test;
/*
* Collection接口
*
* Map接口
* |------HashMap:Map的主要实现类
* |------LinkedHashMap:使用链表维护添加进Map中的顺序。故遍历Map时,是按照添加的顺序进行遍历的。
* |------TreeMap:按照添加进Map中的元素的key的指定属性进行排序。 要求:key必须是同一个类对象。
* 自然排序 & 定制排序
* |------HashTable:古老的实现类,线程安全,不建议使用。
* |------Properties:常用来处理属性文件。特点:键和值都为String类型的。
* */
import com.atguigu.Collection.Customer;
public class TestMap {
/*
* 使用Properties处理属性文件(讲的是输出属性文件中key对应的value属性值)
* */
@Test
public void testProperties() throws FileNotFoundException, IOException{
Properties pros=new Properties();
pros.load(new FileInputStream("jdbc.properties"));//到此为止已经可以用load载入"jdbc.properties"文件了
String user=pros.getProperty("user");//获取属性文件"jdbc.properties"中的数据
System.out.println(user); //将属性文件中的信息逮入进来
String pass=pros.getProperty("password");
System.out.println(pass);
}
//|------TreeMap:按照添加进Map中的元素的key的指定属性进行排序。 要求:key必须是同一个类对象。
//定制排序
@Test
public void testTreeMap2() {
Comparator com=new Comparator() {
@Override //实现排序的方式
public int compare(Object o1, Object o2) {
if(o1 instanceof Customer && o2 instanceof Customer) {
Customer c1=(Customer)o1;
Customer c2=(Customer)o2;
int i=c1.getId().compareTo(c2.getId());
if(i==0) {
return c1.getName().compareTo(c2.getName());
}
return i;
}
return 0;
}
};
Map map=new TreeMap();
map.put(new Person("AA",23), 80);
map.put(new Person("MM",23), 70);
map.put(new Person("CC",13), 80);
map.put(new Person("BB",43), 60);
Set set=map.keySet();
for(Object obj:set) {
System.out.println(obj+"------>"+map.get(obj));
}
}
//自然排序
@Test
public void testTreeMap() {
Map map=new TreeMap();
map.put(new Person("AA",23), 80);
map.put(new Person("MM",22), 70);
map.put(new Person("CC",13), 80);
map.put(new Person("BB",43), 60);
Set set=map.keySet();
for(Object obj:set) {
System.out.println(obj+"------>"+map.get(obj));
}
}
/*
* LinkedHashMap:使用链表维护添加进Map中的顺序。故遍历Map时,是按照添加的顺序遍历的。
* */
@Test
public void testLinkedHashMap() {
Map map=new LinkedHashMap();
map.put("AA ", 213);
map.put("123", 34);
map.put(456, 22);
map.put(new Person("MM",23), 80);
Set set=map.keySet();
for(Object obj:set) {
System.out.println(obj+"------>"+map.get(obj));
}
}
/*
* 如何遍历Map
* Set keySet()
* Collection values()
* Set entrySet()
* */
@Test
public void testMap2() {
Map map=new HashMap();
map.put("AA", 213); //正是因为key是不可重复的所有Entry才不可重复。
map.put("BB", 456);
map.put(123, "CC");
map.put(null, null);
map.put(new Person("DD",23), 89);
//1、遍历key集(用".keySet"):输出的结果与添加进HashMap的顺序不同。
Set set=map.keySet();
for(Object obj:set) {
System.out.println(obj);
}System.out.println(" ****** ");
//2、遍历value集:用".values"
Collection values=map.values();
Iterator i=values.iterator();
while(i.hasNext()) {
System.out.println(i.next());
}
//3、如何遍历key-value对
// 方式一:
Set set1=map.keySet();
for(Object obj:set1) {//通过key找相应的value值
System.out.println(obj+"------>"+map.get(obj));
}
// 方式二:
Set set2=map.entrySet();
for(Object obj:set2) {
Map.Entry entry=(Map.Entry)obj;//创建一个Map.Entry类型的。
// System.out.println(entry.getKey()+"------>"+entry.getValue());
System.out.println(entry);
}
}
/*
* HashMap:
* 1、key是用Set来存放的,不可重复。value是用Collection来存放的,可重复;
*一个key-value对,是一个Entry。所有的Entry是用Set存放的,也是不可重复的。
* 2、向HashMap中添加元素时,会调用key所在类的equals()方法,判断两个key是否相同。
* 若相同则只能添加进后添加的那个元素。
* */
@Test
public void testMap1() {
Map map=new HashMap(); //1、Object put(Object key,Object value):向Map中添加一个元素
// map.put(key, value);
map.put("AA", 213); //正是因为key是不可重复的所有Entry才不可重复。
map.put("BB", 456);
map.put("BB", 456);
map.put(123, "CC");
map.put(null, null);
map.put(new Person("DD",23), 89);//put的两个Person实体类对象添加成功一个,因为key值不能相等。
map.put(new Person("DD",23), 98);
System.out.println(map.size());//结果为:4(因为put()里添加了一个key值重复的,只能算一个。)
System.out.println(map);
/*
* 结果:
5
{AA=213, BB=456, null=null, 123=CC, com.atguigu.Map00.Person@14c8c=98}
*/
map.remove("AA");
System.out.println(map.size());
System.out.println(map);
// map.clear(); //clear:清空Map集合
System.out.println(map.get(123));//get:输出key值为123对应的value值;如果没有此key则返回null。
}
}