1. Map
1.1 Map概述
Map 地图,映射关系。
ORM 对象关系映射 类对象 <==> 数据库数据
双边队列
数据存储形式都是键(Key)值(Value)对形式
表格??
姓名 骚磊
年龄 16
性别 男
Map双边队列中对于数据存储类型
有限制 存储数据类型在创建Map双边队列时进行约束,保证数据类型一致化
但是也没限制 Map可以满足任意类型
Map使用了两个泛型!!!
Map<K, V>
1.2 Map整体结构和常用API
interface Map<K, V>
--| class HashMap<K, V>
底层存储数据结构采用的方式是哈希表方式。存储数据时根据当前存储Key作为计算存储位置,和查询元素的唯一表示。
--| class TreeMap<K, V>
底层存储数据结构是一个二叉树结构,要求存储的键值对,Key必须有对应排序方式。这里就需要Comparator<T> 或者 Comparable<T>
常用
API Application Programing Interface
SDK Software Development Kits
增
put(K key, V value);
添加符合Map要求的键值对存入到双边队列中
putAll(Map<? extends K, ? extends V> map)
添加另一个Map到当前Map中,要求K是当前Map本身对应的K,或者其子类
V是当前Map本身对应的V,或者其子类
删
remove(Object key);
删除对应Key键值对
改
put(K key, V value);
使用value修改已存在的key对应的值
查
int size();
Map双边队列个数
boolean isEmpty();
判断当前Map双边队列中是否为空
boolean containsKey(Object key);
判断指定Key是否存在
boolean containsValue(Object value);
判断指定Value是否存在
Set<K> keySet();
返回Map双边队列中所有Key对应的Set集合
Collection<V> values();
返回Map双边队列中所有value对应Collection集合
【补充】
setId
setName
以上方法是Setter方法,设置类对象属性的方法
keySet
返回值类型是一个Set集合,具有数据存储唯一性
values
以s结尾的方法,表示复数,一般返回值类型都是Collection,List或者数组
总结:
set开头 设置方法
get开头 获取方法
Set结尾,返回值是Set集合,数据唯一
s结尾,返回值类是Collection,List或者数组
1.3 HashMap方法演示
package com.qfedu.a_map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo1 {
public static void main(String[] args) {
Map<String, Integer> map1 = new HashMap<String, Integer>();
map1.put("Dior 999", 280);
map1.put("YSL", 220);
map1.put("Mac", 180);
map1.put("阿玛尼 405", 230);
System.out.println(map1);
Map<String, Integer> map2 = new HashMap<String, Integer>();
map2.put("TF", 179);
map2.put("雅诗兰黛", 229);
map1.putAll(map2);
System.out.println(map1);
map1.remove("Mac");
System.out.println(map1);
map1.put("阿玛尼 405", 280);
System.out.println(map1);
System.out.println(map1.size());
System.out.println(map1.isEmpty());
System.out.println(map1.containsKey("YSL"));
System.out.println(map1.containsKey("杨树林"));
System.out.println(map1.containsValue(179));
System.out.println(map1.containsValue(100));
Set<String> keySet = map1.keySet();
System.out.println(keySet);
Collection<Integer> values = map1.values();
System.out.println(values);
}
}
1.4. TreeMap演示
package com.qfedu.a_map;
import java.util.TreeMap;
public class Demo2 {
public static void main(String[] args) {
TreeMap<Person, Integer> treeMap = new TreeMap<Person, Integer>(new MyComparator());
Person person = new Person(1, "骚磊", 16);
treeMap.put(person, 100);
treeMap.put(new Person(2, "骚杰", 26), 100);
treeMap.put(new Person(3, "宝哥", 16), 200);
treeMap.put(new Person(4, "茂林", 56), 100);
treeMap.put(new Person(5, "康爷", 76), 100);
treeMap.put(new Person(6, "大熊", 96), 100);
System.out.println(treeMap);
System.out.println(treeMap.size());
treeMap.put(new Person(6, "大熊", 96), 200);
System.out.println(treeMap);
System.out.println(treeMap.size());
person.setAge(96);
System.out.println(treeMap);
}
}
package com.qfedu.a_map;
import java.util.Comparator;
public class MyComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
System.out.println("Comparator接口操作");
return o1.getAge() - o2.getAge();
}
}
public class Person {
private int id;
private String name;
private int age;
}
1.5 关于Map键值对整体思想
Map双边队列中把Key和Value进行一个封装操作,完全按照一个数据类型来处理
例如:
class Entry<K, V> {
K k;
V v;
......
}
Map双边队列中提供了操作Entry的方法
Set<Map.Entry<K, V>> entrySet();
返回值类型是Entry键值对形式数据的Set集合
Set<Map.Entry<K, V>>
Map.Entry<K, V> Map接口的内部接口Entry,使用的泛型 K,V对应Map
创建过程中约束的K,V
因为返回值是Set集合,集合带有泛型 Set<Map接口中的内部接口Entry>
Entry对应的API
K getKey();
V getValue();
V setValue(V value);
package com.qfedu.a_map;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
public class Demo3 {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("迈巴赫", "好");
map.put("兰博基尼", null);
map.put("科尼塞克", "太贵了。。。");
map.put("布加迪", "威龙");
map.put("五菱宏光", "神车");
Set<Entry<String,String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
System.out.println(entry.setValue("都比较贵"));
}
}
}
1.6 小总结
1. Map很重要,尤其是HashMap,键值对操作在后期开发中非常常见。
数据库,Session Cookie 数据传递 Json XML...
2. 比较器接口一定要学会使用!!!
Comparator [重点] 自由度非常高,满足各种条件!!!
Comparable
2. 项目更新
2.1 Comparator接口升级改造
希望该排序方法
1. 排序的内容由用户决定
a. 数组
b. 泛型
2. 排序的规则由用户决定【暂时完成!!!】
方法声明:
public static <T> void selectSort(T[] arr, Comparator<T> com)
这是一个工具方法? √
还是属于哪一个类的成员方法?
package com.qfedu.student.system.util;
import java.util.Comparator;
public class MyUtils {
public static <T> void selectSort(T[] arr, Comparator<T> c) {
for (int i = 0; i < arr.length - 1; i++) {
int index = i;
for (int j = i + 1; j < arr.length; j++) {
if (c.compare(arr[index], arr[j]) > 0) {
index = j;
}
}
if (index != i) {
T temp = arr[index];
arr[index] = arr[i];
arr[i] = temp;
}
}
}
}
2.2 匿名内部类使用【重点】
2.2.1 说重点思想
说重点!!!
目前Comparator接口的使用过程
1. 方法参数是Comparator接口
2. 需要完成Comparator接口实现类
3. Comparator接口实现类中完成compare方法
4. compare方法约束比较规则
实现类的名字很重要吗???
1. 知道数据类型
2. 方便new对象操作
3. 方便调用方法
2.2.2 类的本体
class Person {
private int id;
public void test() {
}
}
大括号里面的所有内容都是类的本体!!!
Person只不过是大括号内容一个名字,方便我们操作。
class MyComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
}
大括号里面的内容就是MyComparator类的本体
大括号里面的内容是强迫实现的!!!因为遵从Comparator接口
类定义完毕之后,需要创建对象
MyComparator com = new MyComparator();
com.compare(arg1, arg2);
匿名内部类没有类名,只有类的本体!!!
{
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
}
这部分代码,可不说随便完成的,是需要【遵从Comparator】之后完成的。
使用过程中,compare方法是一个成员方法,需要一个类对象来调用。
Comparator<Person> com = new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
};
这就是一个匿名内部的对象
2.2.3 体会一下匿名内部类
package com.qfedu.b_anonymous;
import java.util.Comparator;
public class Demo1 {
public static void main(String[] args) {
Person[] personArr = new Person[10];
for (int i = 0; i < personArr.length; i++) {
int id = i + 1;
String name = "Person" + i;
int age = (int) (Math.random() * 100);
personArr[i] = new Person(id, name, age);
}
Comparator<Person> com = new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o2.getAge() - o1.getAge();
}
};
MyUtils.selectSort(personArr, com);
for (Person person : personArr) {
System.out.println(person);
}
}
}
package com.qfedu.b_anonymous;
import java.util.Comparator;
public class Demo2 {
public static void main(String[] args) {
Dog[] dogArr = new Dog[10];
for (int i = 0; i < dogArr.length; i++) {
int id = i + 1;
String name = "Dog" + i;
int age = (int) (Math.random() * 100);
dogArr[i] = new Dog(id, name, age);
}
MyUtils.selectSort(dogArr, new Comparator<Dog>() {
@Override
public int compare(Dog o1, Dog o2) {
return o2.getAge() - o1.getAge();
}
});
for (Dog dog : dogArr) {
System.out.println(dog);
}
}
}
2.2.4 匿名内部类总结
SpringBoot SpringCloud
JDK1.8新特征一定要会!!!
Lambda Stream 函数式接口
匿名内部类格式:
最原始格式
接口名 接口引用数据类型变量 = new 接口名() {
// 当前接口要求实现类完成的方法。
}
接口引用数据类型变量调用方法使用,或者作为方法的参数传入
匿名内部类的匿名对象直接作为方法参数
Method(new 接口名() {
// 当前接口要求实现类完成的方法。
});
简化代码冗余度,提高效率,增强功能。
interface A {
public void test();
}
main() {
A a = new A() {
@Override
public void test() {
System.out.println("匿名内部类的对象赋值给接口的引用数据类型变量");
}
};
a.test();
new A() {
@Override
public void test() {
System.out.println("匿名内部类的匿名对象直接调用成员方法");
}
}.test();
testInterface(new A() {
@Override
public void test() {
System.out.prinltn("匿名内部类的匿名对象直接作为方法参数");
}
});
}
public static void testInterface(A a) {
a.test();
}