Java笔记_13
- 一、双列集合
- 1.1、Map的常见API
- 1.2、Map遍历方式一(键找值)
- 1.3、Map集合遍历方法二(键值对)
- 1.4、Map集合遍历方法三(lambda表达式)
- 1.5、HashMap
- 1.6、HashMap练习
- 1.7、HashMap底层源码解析
- 1.7、LinkedHashMap
- 1.8、TreeMap
一、双列集合
双列集合体系结构:
双列集合的特点:
- 双列集合一次需要存一对数据,分别为键和值
- 键不能重复,值可以重复
- 键和值是一一对应的,每一个键只能找到自己对应的值
- 键+值这个整体我们称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”
1.1、Map的常见API
Map是双列集合的顶层接口,它的功能是全部双列集合都可以继承使用的
方法名称 | 说明 |
---|---|
v put(K key,v value) | 添加元素 |
v remove(object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(object key) | 判断集合是否包含指定的键 |
boolean containsValue(object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
put
方法细节- 在添加数据的时候,如果键不存在,那么直接把键值对对象添加到Map集合中,方法返回null
- 在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回。
package Collection_two_Dome.MapDome;
import java.util.HashMap;
import java.util.Map;
public class Dome1 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("康师傅","kangshufu");
map.put("可口","百事");
map.put("段子","皮皮");
map.put("可口","美年达");//会覆盖上面的可口
map.put("段子","123");
System.out.println(map);
map.remove("康师傅");
System.out.println(map);
System.out.println(map.size());//集合长度
//判断是否存在键
boolean keyResult = map.containsKey("康师傅");
System.out.println(keyResult);
//判断是否存在值
boolean ValueResult = map.containsValue("美年达");
System.out.println(ValueResult);
//清空
map.clear();
System.out.println(map.isEmpty());
System.out.println(map);
}
}
1.2、Map遍历方式一(键找值)
三种遍历方式
- 迭代器遍历
- 增强for遍历
- forEach遍历
package Collection_two_Dome.MapDome;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
public class Dome2 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("可乐",3);
map.put("康师傅",1);
map.put("汇源",5);
map.put("沙市",4);
Iterator it = map.keySet().iterator();
while (it.hasNext()){
Object next = it.next();
int money = map.get(next);
System.out.println(next +"="+money);
}
System.out.println("--------- ------------------------------");
Set<String> strings = map.keySet();
for (String string : strings) {
int money = map.get(string);
System.out.println(string+"="+money);
}
strings.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
Integer money = map.get(s);
System.out.println(s+"="+money);
}
});
}
}
1.3、Map集合遍历方法二(键值对)
- 利用
entrySet
方法返回一个Set集合 - 这个集合里面装的是键值对对象
- 在通过
get
方法分别得到key
和value
package Collection_two_Dome.MapDome;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Dome3 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("可乐",3);
map.put("康师傅",1);
map.put("汇源",5);
map.put("沙市",4);
//通过entrySet()方法获得装键值对的set集合
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
//通过get方法依次得到键和值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"="+value);
}
}
}
1.4、Map集合遍历方法三(lambda表达式)
方法名称 | 说明 |
---|---|
default void forEach(Biconsumer<? super K,? super V> action) | 结合lambda遍历Map集合 |
package Collection_two_Dome.MapDome;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
public class Dome4 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("可乐",3);
map.put("康师傅",1);
map.put("汇源",5);
map.put("沙市",4);
map.forEach(new BiConsumer<String, Integer>() {
@Override
public void accept(String s, Integer integer) {
System.out.println(s+"="+ integer);
}
});
System.out.println("-----------------------------------");
map.forEach((String s, Integer integer)->{
System.out.println(s+"="+ integer);
}
);
System.out.println("-----------------------------------");
}
}
1.5、HashMap
HashMap的特点
- HashMap是Map里面的一个实现类。
- 没有额外需要学习的特有方法,直接使用Map里面的方法就可以了。
- 特点都是由键决定的:无序、不重复、无索引
- HashMap跟HashSet底层原理是一模一样的,都是哈希表结构
- 依赖
hashcode
方法和equals
方法保证键的唯一
- 如果键存储的是自定义对象,需要重写hashCode和equals方法
- 如果值存储的是自定义对象,不需要重写hashCode和equals方法
1.6、HashMap练习
package Collection_two_Dome.HashMapDome;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
public class Dome1 {
public static void main(String[] args) {
HashMap<student,String> hm = new HashMap<>();
student s1 = new student("xiaoming",18);
student s2 = new student("xiaowang",19);
student s3 = new student("xiaoli",18);
student s4 = new student("xiaoming",18);
hm.put(s1,"henan");
hm.put(s2,"guangdong");
hm.put(s3,"jiangsu");
hm.put(s4,"shandong");
hm.forEach((student student, String s)->{
System.out.println(student+" "+s);
}
);
System.out.println("-------------------------------------");
Set<Map.Entry<student, String>> hms = hm.entrySet();
for (Map.Entry<student, String> studentStringEntry : hms) {
System.out.println(studentStringEntry);
}
System.out.println("-------------------------------------");
Iterator it = hm.entrySet().iterator();
while (it.hasNext()){
Object next = it.next();
System.out.println(next);
}
}
}
package Collection_two_Dome.HashMapDome;
import java.util.*;
public class Dome2 {
public static void main(String[] args) {
//创建数组,记录四个景点
String[] arr = {"黄山","泰山","华山","佘山"};
//利用随机数模拟80个同学的投票票
//通过集合的形式记录每个景点的票数
Random r =new Random();
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 80; i++) {
int index = r.nextInt(arr.length);
list.add(arr[index]);
}
//定义Map集合,利用集合进行统计
HashMap<String,Integer> hm = new HashMap<>();
for (String name : list) {
//判断当前景点在map集合中是否存在
if(hm.containsKey(name)){
//先得到这个景点的次数
int count = hm.get(name);
//在进行++
count++;
//重新存入
hm.put(name,count);
}else {
hm.put(name,1);
}
}
System.out.println(hm);
//求最大值
int max = 0;
//比较得出最大值
Set<Map.Entry<String, Integer>> entries = hm.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
if(entry.getValue()>max){
max= entry.getValue();
}
}
System.out.println(max);
//再次通过遍历的到最大票数的景点
for (Map.Entry<String, Integer> entry : entries) {
if (max== entry.getValue()){
System.out.println(entry.getKey());
}
}
}
}
1.7、HashMap底层源码解析
添加第一个元素的底层原理
数组位置不为null,键不重复,挂在下面形成链表或者红黑树
1.7、LinkedHashMap
- 由键决定:有序、不重复、无索引。
- 这里的有序指的是保证存储和取出的元素顺序一致
- 原理∶底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。
package Collection_two_Dome.LinkedHashMapDome;
import java.util.LinkedHashMap;
public class Dome1 {
public static void main(String[] args) {
LinkedHashMap<String,Integer> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("可乐",3);
linkedHashMap.put("百事",3);
linkedHashMap.put("沙市",4);
linkedHashMap.put("北冰洋",5);
linkedHashMap.put("可口",3);
linkedHashMap.put("芬达",3);
linkedHashMap.put("雪碧",3);
linkedHashMap.put("可乐",4);//键相同时,回覆盖掉原来的值
System.out.println(linkedHashMap);
}
}
1.8、TreeMap
- TreeMap跟TreeSet底层原理一样,都是红黑树结构的。
- 由键决定特性:不重复、无索引、可排序
- 可排序:对键进行排序。
- 注意:默认按照键的从小到大进行排序,也可以自己规定键的排序规则
代码书写两种排序规则
- 实现Comparable接口,指定比较规则。
- 创建集合时传递Comparator比较器对象,指定比较规则。
package Collection_two_Dome.TreeMapDome;
import java.util.Comparator;
import java.util.TreeMap;
public class Dome1 {
public static void main(String[] args) {
TreeMap<Integer,String> tm = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;//此时Integer按照降序排列
}
});
//默认情况下Integer 和Double类型是按照升序的方法进行排列
tm.put(1,"火车");
tm.put(4,"游艇");
tm.put(5,"出租");
tm.put(2,"公交");
tm.put(7,"大巴");
tm.put(6,"汽车");
tm.put(8,"飞机");
System.out.println(tm);
}
}
package Collection_two_Dome.TreeMapDome;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class Dome2 {
public static void main(String[] args) {
TreeMap<Student,String> tm = new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int i = o1.getAge()- o2.getAge();
i = i==0?o1.getName().compareTo(o2.getName()):i;
return i;
}
});
Student s1 = new Student("chen",18);
Student s2 = new Student("lu",19);
Student s3 = new Student("huang",17);
Student s4 = new Student("jia",19);
Student s5 = new Student("qian",18);
Student s6 = new Student("gao",20);
tm.put(s1,"广东");
tm.put(s2,"河南");
tm.put(s3,"四川");
tm.put(s4,"山西");
tm.put(s5,"江苏");
tm.put(s6,"云南");
Set<Map.Entry<Student, String>> entries = tm.entrySet();
for (Map.Entry<Student, String> entry : entries) {
System.out.println(entry);
}
}
}
package Collection_two_Dome.TreeMapDome;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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 String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
package Collection_two_Dome.TreeMapDome;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.function.BiConsumer;
public class Dome3 {
public static void main(String[] args) {
String s = "asdasdasdasdasdddasdasdaddadfffaasffafasffff";
TreeMap<Character,Integer> tm = new TreeMap<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(tm.containsKey(c)){
Integer count = tm.get(c);
count++;
tm.put(c,count);
}else {
tm.put(c,1);
}
}
StringBuilder sb = new StringBuilder();
tm.forEach((character,integer)->sb.append(character).append("(").append(integer).append(")"));
System.out.println(sb);
//使用StringJoiner方法时需要定义开头末尾以及中间每个元素之间的间隔字符
StringJoiner sj =new StringJoiner("","","");/*使用StringJoiner的add方法时一定要添加字符串&*/
tm.forEach(( character, integer)->sj.add(character+"").add("(").add(integer+"").add(")"));
System.out.println(sj);
}
}