Map
1.1概述
-
Map:双列集合的顶层接口
-
Map:描述的就是一个数据(key)到另一个数据(value)的对应关系
-
一个数据(key):就是有规律的,容易记忆的,简单的一个数据
-
一个数据(value):没有规律的,不容易记忆的,复杂的一个数据
-
大多数都是根据key来寻找value
-
-
Map的特点:
-
Key(键)是唯一的
-
Value(值)不是唯一的
-
-
Map和Collection的区别:
-
Map是双列集合
-
Collection是单列集合
-
Map的键是唯一的,Collection中的Set子接口中的元素是唯一的
-
Map的所有操作是针对《键》有效,Collection中的set子接口中的操作针对《元素》有效
-
1.2Map中的常用方法
-
增加键值对:
-
put(K key, V value)
-
-
删除方法:
-
根据给定的键,删除对应的键值对:
-
remove (K key)
-
清空集合:clear()
-
-
-
获取方法:
-
获取集合的大小:size()
-
获取键对应的值,根据给定的键,获取对应的值:V get(K key)
-
-
判断方法:
-
判断集合中是否存在某个键:containsKey(Object obj)
-
判断集合中是否存在某个值:containsValue(Object obj)
-
-
修改方法:
-
根据给定的键,修改对应的值:put(K key, V value)
-
如果在集合中已经存在key这个键,那么使用put方法,就是修改其对应的值
-
如果集合中不存在key这个键,那么使用put方法,就是在集合中增加了一个键值对
-
-
代码示例:
import java.util.HashMap;
import java.util.Map;
/**
*Map中的常用方法
*/
public class Simple01 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
map.put("c", 4);
System.out.println(map);
map.remove("a");
System.out.println(map);
map.clear();
System.out.println(map);
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
map.put("d", 4);
System.out.println(map.size());
Integer value = map.get("c");
System.out.println(value);
boolean b = map.containsKey("bb");
System.out.println(b);
boolean b1 = map.containsValue(4);
System.out.println(b1);
map.put("a", 11);
System.out.println(map.get("a"));
map.put("aa", 111);
System.out.println(map);
}
}
1.3 Map集合的第一种遍历思路【熟练掌握】
-
获取Map集合中的所有键,放到一个Set集合中,遍历该Set集合,获取到每一个键,根据键再来获取对应的值。【根据键获取值】
-
获取Map集合中的所有键并存入Set
Set<K> keySet() //k是你map中键的类型,Set<String> set = map.keySet();
-
遍历Set集合的两种方法:
-
迭代器
-
增强for循环
-
-
拿到每个键之后,获取对应的值 V get(K key)
-
特点: 获取了所有的键的集合之后,仍然要依赖原来的Map集合
代码示例:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Map集合的第一种遍历思路【熟练掌握】
*/
public class Simple02 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap();
map.put("aaa", 111);
map.put("bbb", 222);
map.put("ccc", 333);
map.put("ddd", 444);
System.out.println(map);
// test1(map);//第一种遍历思路的第一种遍历方式迭代器(map)
test2(map);// 第一种遍历思路的第二种遍历方式增强for(map)
}
// 第一种遍历思路的第一种遍历方式迭代器(map)
public static void test1(Map<String, Integer> map) {
Set<String> set = map.keySet();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String key = it.next();
System.out.println("key是:" + key + "---value是:" + map.get(key));
}
}
// 第一种遍历思路的第二种遍历方式增强for(map)
public static void test2(Map<String, Integer> map) {
Set<String> set = map.keySet();
for (String key : set) {
System.out.println("key是:" + key + "---value是:" + map.get(key));
}
}
}
1.4 Map集合的第二种遍历思路【熟练掌握】
-
获取Map集合中的所有键值对对象(Entry)到Set集合中,遍历Set集合,拿到的是每个键值对对象(Entry),从这个对象中分别获取键和值【根据键值对对象获取键和值】
-
根据Map集合获取所有的键值对对象,到一个Set集合中
-
Set<Map.Entry<K, V>> entrySet() Set<Map.Entry<String, String>> set = map.entrySet();
-
遍历Set集合,两种遍历方式
-
迭代器
-
增强for循环
-
-
获取到某个键值对对象
-
Entry是Map接口中的内部接口,访问的方式:Map.Entry
-
Entry:入口、条目、登记记录
-
Entry的常用方法:
-
getKey()获取当前键值对对象的键
-
getValue()获取当前键值对对象的值
-
-
代码示例:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Map集合的第二种遍历思路【熟练掌握】
*/
public class Simple03 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("username", "zhangsan");
map.put("password", "123456");
map.put("nickname", "miaomi");
System.out.println(map);
test1(map)
test2(map);
}
//迭代器遍历Set集合
public static void test1(Map<String, String> map) {
Set<Map.Entry<String, String>> set = map.entrySet();
System.out.println(set);
Iterator<Map.Entry<String, String>> iterator = set.iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> next = iterator.next();
String key = next.getKey();
String value = next.getValue();
System.out.println("键是:" + key + "---值是:" + value);
}
}
// 增强for循环遍历Set(map)
public static void test2(Map<String, String> map) {
Set<Map.Entry<String, String>> set = map.entrySet();
for (Map.Entry<String, String> st : set) {
System.out.println("键是:" + st.getKey() + "----值是:" + st.getValue());
}
}
}
1.5 HashMap
HashMap 的底层实现方式为哈希表,是 HashSet 的实现原理。
-
就是Map集合使用哈希表的存储方式的一种实现类
-
HashMap存储的是jdk中提供的类型的键,就可以直接保证键的唯一性
-
HashMap中存储的键,是自定义类型(比如下方代码Person),无法保证键的唯一性,原因:虽然都是zhangsan对象,但是这些对象并不是相同的对象,这些对象的哈希值计算结果各不相同,就说明一定不是相同的对象,所以无法保证键的唯一,重写hashCode和equals方法说明:HashMap的键的唯一性和HashSet的元素的唯一性,保证方式都一样
-
HashMap和HashSet的关系:
-
HashSet是由HashMap实现出来的,HashSet就是HashMap的键的那一列
-
将HashMap中的值的那一列隐藏掉,就变成了HashSet
-
-
示例代码:
import java.util.HashMap;
import java.util.Objects;
/**
* HashMap;
*/
public class Simple04 {
public static void main(String[] args) {
HashMap<Person, String> hm = new HashMap<>();
hm.put(new Person("张三", 23), "北京");
hm.put(new Person("张三", 23), "上海");
hm.put(new Person("张三", 23), "广州");
System.out.println(hm);
test1_HashMap存储jdk的键();
}
private static void test1_HashMap存储jdk的键() {
HashMap<String, Integer> hm = new HashMap<>();
hm.put("abc", 1);
hm.put("abc", 3);
hm.put("ab", 2);
hm.put("ab", 4);
System.out.println();
System.out.println("*******************");
System.out.println();
System.out.println(hm);
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
1.6 LinkedHashMap
-
是HashMap的一个子类
-
实现原理哈希表+链表
-
和HashMap不同之处:具有可预知的迭代顺序,存储键值对的顺序和遍历集合时取出键值对的顺序一致。
-
代码示例:
import java.util.LinkedHashMap;
/**
* LinkedHashMap
*/
public class Simple05 {
public static void main(String[] args) {
LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
lhm.put("aa", 3);
lhm.put("bb", 3);
lhm.put("cc", 2);
lhm.put("dd", 4);
System.out.println(lhm);
}
}
1.7 HashMap和Hashtable的关系
-
HashMap和Hashtable都是用于存储键和值的对应关系,都是Map的实现类,都是使用哈希表的方式存储。
-
不同点:
-
版本不同,Hashtable是jdk1.0版本出现的,HashMap是jdk1.2版本出现的
-
线程安全性不同,Hashtable是线程安全的,HashMap是线程不安全的
-
Hashtable不能存储null键null值,HashMap可以存储null键null值
-
-
代码示例:
import java.util.HashMap;
import java.util.Hashtable;
/**
* HashMap和Hashtable的关系
*/
public class Simple06 {
public static void main(String[] args) {
HashMap<String, Integer> hm = new HashMap<>();
hm.put(null, 0);//键可以存null值
hm.put("1", null);//值可以存null值
// hm.put(null, null);//键值可以存null值
System.out.println(hm);
test1_Hashtable存储null键null值();
}
public static void test1_Hashtable存储null键null值() {
//Hashtable 不可以存储null键值
Hashtable<String, Integer> ht = new Hashtable<>();
ht.put("abc", 3);
ht.put(null, 0);
ht.put("", null);
ht.put(null, null);
System.out.println(ht);
}
}
Collections集合工具类
-
java.utils.Collections是集合工具类,用来对集合进行操作。工具类的使用方式是类名.方法 比如Collections.sort(list)
-
常用方法如下:
-
max
-
min
-
addAll
-
reverse
-
shuffle
-
public static void test1() {
ArrayList<Integer> list = new ArrayList<>();
list.add(11);
list.add(33);
list.add(55);
System.out.println(Collections.max(list));
System.out.println(Collections.min(list));
Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
Collections.shuffle(list);
System.out.println(list);
}
-
sort 接口实现
public class CollectionsUtil {
public static void main(String[] args) {
test2();
}
public static void test2() {
/*
* java.utils.Collections是集合工具类,用来对集合进行操作。
* 工具类的使用方式是类名.方法 比如Collections.sort(list)
* 注意被排序的集合里面存储的元素必须要实现Comparable接口,并重写接口中
* 的Compare To 定义排序的规则
* 像案例中的String ,Integer 默认已经实现了Comparable接口
* 但是如果是自定义类就需要手动实现Comparable接口并指定泛型。
* Compare To 定义排序的规则:
* this.属性 - 参数.属性 :升序 ,反之降序
*
* */
ArrayList<Integer> list1 = new ArrayList<>();
Collections.addAll(list1, 1, 44, 55, 22, 12, -45, 0);
Collections.sort(list1);
System.out.println(list1);// 默认升序
ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list2, "a", "b", "aa", "c", "bb");
Collections.sort(list2);
System.out.println(list2);// 默认升序
ArrayList<Animal> list3 = new ArrayList<>();
list3.add(new Animal("佩奇", 3));
list3.add(new Animal("艾米丽", 5));
list3.add(new Animal("苏西", 2));
Collections.sort(list3);
System.out.println(list3);
}
}
class Animal implements Comparable<Animal> {
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public Animal() {
}
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;
}
// 这里不需要重写hashcode 和 equals 方法,因为我们没用set;
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Animal o) {
// return this.getAge() - o.getAge();// 按年龄升序
return o.getAge() - this.getAge();// 按年龄降序
}
}
-
sort 匿名内部类
public class CollectionsUtil {
public static void main(String[] args) {
test3();
}
public static void test3() {
/*
* Comparator 和 Comparable区别
* Comparable区别是自己和别人(参数)比较,需要实现Comparable接口,重写ComparaeTo方法
* Comparator相当于找一个第三方的裁判,比较2个参数的大小,需要使用匿名内部类
* */
ArrayList<Animal> list4 = new ArrayList<>();
list4.add(new Animal("a佩奇", 3));
list4.add(new Animal("b艾米丽", 5));
list4.add(new Animal("a苏西", 5));
// Collections.sort(list4, new Comparator<Animal>() {
// @Override
// public int compare(Animal o1, Animal o2) {
// return o1.getAge() - o2.getAge();
// }
// });
Collections.sort(list4, new Comparator<Animal>() {
@Override
public int compare(Animal o1, Animal o2) {
// 按年龄排序
int result = o1.getAge() - o2.getAge();
// 如果年龄相同按姓名排序
if (result == 0) {
result = o1.getName().charAt(0) - o2.getName().charAt(0);
}
return result;
}
});
System.out.println(list4);
}
}
class Animal {
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public Animal() {
}
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;
}
// 这里不需要重写hashcode 和 equals 方法,因为我们没用set;
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}