1.为什么要学Map集合,因为很多技术的底层用了Map集合,学习Map集合有助力了解技术的底层原理.
2.Map:存储Key-value对.
3.HashMap:按Key-value存值,Key无序,唯一的单一对象.底层采用数组+链表(哈希表)存值.
注意:HashMap想通过Key的值来去重,要求HashMap的Key的泛型类型中重写hashCode()和equals().
Key唯一性:通过hashCode()和equals()方法实现的.
eg:public class Mouse2 {
public String mname;
public String breed;
public Mouse2() {
}
public Mouse2(String mname, String breed) {
super();
this.mname = mname;
this.breed = breed;
}
@Override
public String toString() {
return "Mouse2 [mname=" + mname + ", breed=" + breed + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((breed == null) ? 0 : breed.hashCode());
result = prime * result + ((mname == null) ? 0 : mname.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;
Mouse2 other = (Mouse2) obj;
if (breed == null) {
if (other.breed != null)
return false;
} else if (!breed.equals(other.breed))
return false;
if (mname == null) {
if (other.mname != null)
return false;
} else if (!mname.equals(other.mname))
return false;
return true;
}
}
public static void main(String[] args) {
//创建对象
HashMap<Mouse2, String> hmap1=new HashMap<>();
//向集合添加元素
hmap1.put(new Mouse2("jerry", "米老鼠1"), "ff1");
hmap1.put(new Mouse2("aa", "米老鼠2"), "aa1");
hmap1.put(new Mouse2("dd", "米老鼠2"), "hh1");
hmap1.put(new Mouse2("cc", "米老鼠2"), "cc1");
hmap1.put(new Mouse2("jerry", "米老鼠1"), "ff3");
/*第一种:遍历Map集合*/
//将Map集合中Key-value对作为整体存entry类型,将Map集合转换entry类型set集合
Set<Entry<Mouse2,String>> set1=hmap1.entrySet();
//获得set集合迭代器对象
Iterator<Entry<Mouse2, String>> it1=set1.iterator();
//每判断一次迭代一次
while (it1.hasNext()) {
Entry<Mouse2, String> e1=it1.next();
System.out.println("键为:"+e1.getKey()+",值为:"+e1.getValue());
}
System.out.println("**********************************");
//删除集合中元素
hmap1.remove(new Mouse2("cc", "米老鼠2"));
/*第二种:遍历Map集合*/
//获得map集合中扭有Key
Set<Mouse2> set2=hmap1.keySet();
//遍历所有Key
for (Mouse2 key1: set2) {
//获得当前遍历Key,根据Map集合中Key得到Value
System.out.println("键为:"+key1+",值为:"+hmap1.get(key1));
}
}
4.LinkedHashMap(了解):按key-value方式存值,Key有序,唯一的单一对象.
层采用哈希表和链表结构存值.
eg:public static void main(String[] args) {
//创建对象
HashMap<Mouse2, String> hmap1=new LinkedHashMap<>();
//向集合添加元素
hmap1.put(new Mouse2("jerry", "米老鼠1"), "ff1");
hmap1.put(new Mouse2("aa", "米老鼠2"), "aa1");
hmap1.put(new Mouse2("dd", "米老鼠2"), "hh1");
hmap1.put(new Mouse2("cc", "米老鼠2"), "cc1");
hmap1.put(new Mouse2("jerry", "米老鼠1"), "ff3");
/*第一种:遍历Map集合*/
//将Map集合中Key-value对作为整体存entry类型,将Map集合转换entry类型set集合
Set<Entry<Mouse2,String>> set1=hmap1.entrySet();
//获得set集合迭代器对象
Iterator<Entry<Mouse2, String>> it1=set1.iterator();
//每判断一次迭代一次
while (it1.hasNext()) {
Entry<Mouse2, String> e1=it1.next();
System.out.println("键为:"+e1.getKey()+",值为:"+e1.getValue());
}
System.out.println("**********************************");
//删除集合中元素
hmap1.remove(new Mouse2("cc", "米老鼠2"));
/*第二种:遍历Map集合*/
//获得map集合中扭有Key
Set<Mouse2> set2=hmap1.keySet();
//遍历所有Key
for (Mouse2 key1: set2) {
//获得当前遍历Key,根据Map集合中Key得到Value
System.out.println("键为:"+key1+",值为:"+hmap1.get(key1));
}
}
5.TreeMap:按Key-value对存值,Key无序可排序,唯一的单一对象.底层采用红黑二叉树存值.
注意:TreeMap的Key一定要用排序器,如果创建TreeMap时用无参构造,默认采用的是自然排序器,TreeMap的Key的类型中实现自然排序器接口,重写排序方法;如果TreeMap的Key要用自定义排序器,那么TreeMap的构造方法中要传入自定义排序器对象作为参数,自己手写自定义排序器类重写排序方法.
Key的可排序性:通过排序器的排序方法返回正数(1)排在后面,返回负数(-1)排在前面.
Key的唯一性:通过排序器的排序方法返回0,Key不存,Value覆盖.
TreeMap存值原理:添加Key-value对时,看二叉树根节点是否为null,如果为null,当前
Key-value就作为根节点;如果根节点不为空,取出当前Key-value的Key调用排序器的排序
方法与根节点比较,返回正数,负数和0. 如果返回0,就表示当前节点与根节点相同,Key不
存,value覆盖.如果返回负数(-1),就看根节点有无左子节点,如果根节点无左子节点,当前
Key-value就存在根节点的左子节点处,如果有左子节点,将当前Key与左子节点继续,直到
找到存值处;如果返回正数(1),就看根节点有无右子节点,如果无,直接存在右子节点处,如
果有就与右子节点继续比较,直到找到存值的位置.
eg:public static void main(String[] args) {
//创建对象
TreeMap<String, String> hmap1=new TreeMap<>();
//向集合添加元素
hmap1.put("ff", "ff1");
hmap1.put("aa", "aa1");
hmap1.put("hh", "hh1");
hmap1.put("cc", "cc1");
hmap1.put("ff", "ff2");
/*第一种:遍历Map集合*/
//将Map集合中Key-value对作为整体存entry类型,将Map集合转换entry类型set集合
Set<Entry<String,String>> set1=hmap1.entrySet();
//获得set集合迭代器对象
Iterator<Entry<String, String>> it1=set1.iterator();
//每判断一次迭代一次
while (it1.hasNext()) {
Entry<String, String> e1=it1.next();
System.out.println("键为:"+e1.getKey()+",值为:"+e1.getValue());
}
System.out.println("**********************************");
//删除集合中元素
hmap1.remove("cc");
/*第二种:遍历Map集合*/
//获得map集合中扭有Key
Set<String> set2=hmap1.keySet();
//遍历所有Key
for (String key1: set2) {
//获得当前遍历Key,根据Map集合中Key得到Value
System.out.println("键为:"+key1+",值为:"+hmap1.get(key1));
}
}
6.排序器:
6.1:自然排序器(Comparable)
eg:/**
* 猫类,实现自然排序器接口,重写排序方法
* @author sx
* @version 2020年1月13日
*/
public class Cat2 implements Comparable<Cat2>{
/**
* 自然排序器的排序方法
* @param o表示从根节点开始,每个要比较的对象
* @return 返回值,返回负数(-1)排在前面,返回正数(1)排在后面,返回0表示相同元素
* 先按昵称按字典顺序升序排,当昵称相同,按品种的字典顺序降序排
*/
@Override
public int compareTo(Cat2 o) {
if (this.nickName.compareTo(o.nickName)!=0) {
return this.nickName.compareTo(o.nickName);
}else {//昵称相同,按品种
if (this.breed.compareTo(o.breed)!=0) {//昵称相同,按品种不同
return -this.breed.compareTo(o.breed);
} else {//昵称相同,按品种相同
return 0;
}
}
}
public String nickName;
public String breed;
public Cat2() {
}
public Cat2(String nickName, String breed) {
super();
this.nickName = nickName;
this.breed = breed;
}
@Override
public String toString() {
return "Cat2 [nickName=" + nickName + ", breed=" + breed + "]";
}
}
public static void main(String[] args) {
//创建对象
TreeMap<Cat2, String> hmap1=new TreeMap<>();
//向集合添加元素
hmap1.put(new Cat2("ff", "tom猫"), "ff1");
hmap1.put(new Cat2("aa", "c猫"), "aa1");
hmap1.put(new Cat2("hh", "aa猫"), "hh1");
hmap1.put(new Cat2("cc", "ff猫"), "cc1");
hmap1.put(new Cat2("ff", "dom猫"), "ff2");
/*第一种:遍历Map集合*/
//将Map集合中Key-value对作为整体存entry类型,将Map集合转换entry类型set集合
Set<Entry<Cat2,String>> set1=hmap1.entrySet();
//获得set集合迭代器对象
Iterator<Entry<Cat2, String>> it1=set1.iterator();
//每判断一次迭代一次
while (it1.hasNext()) {
Entry<Cat2, String> e1=it1.next();
System.out.println("键为:"+e1.getKey()+",值为:"+e1.getValue());
}
System.out.println("**********************************");
//删除集合中元素
hmap1.remove(new Cat2("cc", "ff猫"));
/*第二种:遍历Map集合*/
//获得map集合中扭有Key
Set<Cat2> set2=hmap1.keySet();
//遍历所有Key
for (Cat2 key1: set2) {
//获得当前遍历Key,根据Map集合中Key得到Value
System.out.println("键为:"+key1+",值为:"+hmap1.get(key1));
}
}
6.2:自定义排序器(Comparator)
eg:/**
* 自定义排序器类
* @author sx
* @version 2020年1月13日
*/
public class MyComparator implements Comparator<Cat3>{
/**
* 自定义排序器的排序方法
* @param o1表示当前的对象
* @param o2表示从根节点开始每个要比较节点对象
* 排序规则:先按昵称字典顺序降序排,昵称相同,再按品种升序排
*/
@Override
public int compare(Cat3 o1, Cat3 o2) {
if (o1.nickName.compareTo(o2.nickName)!=0) {
return -o1.nickName.compareTo(o2.nickName);
} else {//昵称相同,再按品种升序排
return o1.breed.compareTo(o2.breed);
}
}
}
public static void main(String[] args) {
//创建自定义排序器对象
MyComparator mc=new MyComparator();
//创建对象,将自定义排序器对象作TreeMap的构造方法参数
TreeMap<Cat3, String> hmap1=new TreeMap<>(mc);
//向集合添加元素
hmap1.put(new Cat3("ff", "tom猫"), "ff1");
hmap1.put(new Cat3("aa", "c猫"), "aa1");
hmap1.put(new Cat3("hh", "aa猫"), "hh1");
hmap1.put(new Cat3("cc", "ff猫"), "cc1");
hmap1.put(new Cat3("ff", "dom猫"), "ff2");
/*第一种:遍历Map集合*/
//将Map集合中Key-value对作为整体存entry类型,将Map集合转换entry类型set集合
Set<Entry<Cat3,String>> set1=hmap1.entrySet();
//获得set集合迭代器对象
Iterator<Entry<Cat3, String>> it1=set1.iterator();
//每判断一次迭代一次
while (it1.hasNext()) {
Entry<Cat3, String> e1=it1.next();
System.out.println("键为:"+e1.getKey()+",值为:"+e1.getValue());
}
System.out.println("**********************************");
//删除集合中元素
hmap1.remove(new Cat3("cc", "ff猫"));
/*第二种:遍历Map集合*/
//获得map集合中扭有Key
Set<Cat3> set2=hmap1.keySet();
//遍历所有Key
for (Cat3 key1: set2) {
//获得当前遍历Key,根据Map集合中Key得到Value
System.out.println("键为:"+key1+",值为:"+hmap1.get(key1));
}
}
6.3:匿名内部类创建自定义排序器对象
eg:/**
* TreeMap的使用,匿名内部类自定义排序器的用法
* @author sx
* @version 2020年1月13日
*/
public class TreeMapTest4 {
public static void main(String[] args) {
//创建对象,将匿名内部类自定义排序器对象作TreeMap的构造方法参数
TreeMap<Cat4, String> hmap1=new TreeMap<>(new Comparator<Cat4>() {
/**
* 自定义排序器匿名内部类的排序方法
* @param o1表示当前的对象
* @param o2表示从根节点开始每个要比较节点对象
* 排序规则:先按昵称字典顺序升序排,昵称相同,再按品种降序排
*/
@Override
public int compare(Cat4 o1, Cat4 o2) {
if (o1.nickName.compareTo(o2.nickName)!=0) {
return o1.nickName.compareTo(o2.nickName);
} else {//昵称相同,再按品种降序排
return -o1.breed.compareTo(o2.breed);
}
}
});
//向集合添加元素
hmap1.put(new Cat4("ff", "tom猫"), "ff1");
hmap1.put(new Cat4("aa", "c猫"), "aa1");
hmap1.put(new Cat4("hh", "aa猫"), "hh1");
hmap1.put(new Cat4("cc", "ff猫"), "cc1");
hmap1.put(new Cat4("ff", "dom猫"), "ff2");
/*第一种:遍历Map集合*/
//将Map集合中Key-value对作为整体存entry类型,将Map集合转换entry类型set集合
Set<Entry<Cat4,String>> set1=hmap1.entrySet();
//获得set集合迭代器对象
Iterator<Entry<Cat4, String>> it1=set1.iterator();
//每判断一次迭代一次
while (it1.hasNext()) {
Entry<Cat4, String> e1=it1.next();
System.out.println("键为:"+e1.getKey()+",值为:"+e1.getValue());
}
System.out.println("**********************************");
//删除集合中元素
hmap1.remove(new Cat4("cc", "ff猫"));
/*第二种:遍历Map集合*/
//获得map集合中扭有Key
Set<Cat4> set2=hmap1.keySet();
//遍历所有Key
for (Cat4 key1: set2) {
//获得当前遍历Key,根据Map集合中Key得到Value
System.out.println("键为:"+key1+",值为:"+hmap1.get(key1));
}
}
}
7.匿名内部类:一个类声明在另一个类的方法中,且这个类没有名字,叫匿名内部类
7.1:匿名内部类适用场景:当一个类一生只有一个对象,这个对象只用一次时,就可以将这个类声明为匿名内部类.
7.2:匿名内部类特点:
7.2.1:匿名内部类一定要有父类或父接口,作为创建对象的数据类型.
7.2.2:匿名内部类必须在声明的同时创建对象,一生只有一个对象.
7.3:匿名内部类使用语法:
new 父接口/父类(){
匿名内部类的类体,里面可以声明成员属性和方法.
};
eg://创建匿名内部类的对象,小括号后面的一对大括号是匿名类的类体,用父接口作为数据类型创建匿名内部类的对象.
IMyself m2=new IMyself(){
/**
* 自我介绍的方法
*/
@Override
public void showMyself(String name) {
System.out.println("大家好,我叫"+name);
}
};
m2.showMyself("张三");
//创建匿名内部类的对象的同时调用方法
new IMyself(){
/**
* 自我介绍的方法
*/
@Override
public void showMyself(String name) {
System.out.println("大家好,我叫"+name);
}
}.showMyself("李四");