带你从零学大数据系列之Java篇---第十九章:集合(Map+Collections)
程序员文章站
2022-07-04 16:00:50
...
课程重点:
- Map的存储特点
- Map的常用方法
- Map的遍历
- TreeMap的去重和排序(了解)
- HashMap的去重(了解)
- Collections工具类中常用方法
19.1. Map集合的存储特点
Map是双列集合的*接口, 这个接口并没有继承自Collection接口。
在Map中, 更多强调的是一层映射关系。 在Map中存储的数据, 是一个个的键值对(Key-Value-Pair), 键和值是一一对应的。
需要注意:
由于Map集合并没有实现Iterable接口, 因此这个集合是不能使用增强for循环遍历的。
19.2. Map API
19.3. 示例代码
import java.util.*;
/**
* @Author 千锋大数据教学团队
* @Company 千锋好程序员大数据
* @Description Map API
*/
public class MapUsage {
public static void main(String[] args) {
// 1. 实例化一个Map集合的实现类对象,并向上转型为接口类型。
Map<String, String> map = new HashMap<>();
// 2. 向集合中插入数据
String value = map.put("name", "xiaoming");
System.out.println(value); // 由于第一次添加这个键值对,集合中没有被覆盖的值,因此返回null
String value2 = map.put("name", "xiaobai");
System.out.println(value2); // 这里是第二次设置name的值,会用xiaobai覆盖掉xiaoming,因此返回xiaoming
// 3. 向集合中插入数据
String value3 = map.putIfAbsent("name", "xiaohong");
System.out.println(value3); // 这里返回的是集合中已经存在的这个键对应的值
String value4 = map.putIfAbsent("age", "20");
System.out.println(value4); // 由于这个集合中原来是没有age键存在的,所以返回的是null
// 4. 将一个Map集合中所有的键值对添加到当前的集合中
Map<String, String> tmp = new HashMap<>();
tmp.put("height", "177");
tmp.put("weight", "65");
tmp.put("age", "30");
map.putAll(tmp);
// 5. 删除:通过键,删除一个键值对,并返回这个被删除的键值对中的值。
String value5 = map.remove("weight");
System.out.println(value5);
// 6. 删除
boolean value6 = map.remove("age", "30");
System.out.println(value6);
// 7. 清空集合
// map.clear();
// 8. 修改集合中的某一个键值对(通过键,修改值)
String value7 = map.replace("name", "xiaohei");
System.out.println(value7); // 返回被覆盖的值
String value8 = map.replace("age", "30");
System.out.println(value8); // 由于map中没有age键,因此这个返回null
// 9. 修改: 只有当key和oldValue是匹配的情况下,才会将值修改成newValue。
boolean value9 = map.replace("name", "xiaohei", "xiaohong");
System.out.println(value9);
// 10. 对集合中的元素进行批量的替换
// 将集合中的每一个键值对,带入到BiFunction的方法中,使用接口方法的返回值替换集合中原来的值。
map.replaceAll((k, v) -> {
if (k.equals("height")) {
return v + "cm";
}
return v;
});
// 11. 通过键获取值。
String value10 = map.get("name1");
System.out.println(value10);
// 12. 通过键获取值,如果这个键不存在,则返回默认的值。
String value11 = map.getOrDefault("name1","aaa");
System.out.println(value11);
// 13. 判断是否包含某一个键
boolean value12 = map.containsKey("height");
System.out.println(value12);
boolean value13 = map.containsValue("177");
System.out.println(value13);
// 14. 获取由所有的键组成的Set集合
Set<String> keys = map.keySet();
// 获取由所有的值组成的Collection集合
Collection<String> values = map.values();
System.out.println(map);
}
}
19.4. Map集合的遍历
19.4.1. 使用keySet进行遍历
- 可以使用keySet()方法获取到集合中所有的键。
- 遍历存储了所有的键的集合,依次通过键获取值。
/**
* 1. 使用keySet进行遍历
* @param map 需要遍历的集合
*/
private static void keyset(Map<String, String> map) {
// 1. 获取存储了所有的键的集合
Set<String> keys = map.keySet();
// 2. 遍历这个Set集合
for (String key : keys) {
// 2.1. 通过键获取值
String value = map.get(key);
// 2.2. 展示一下键和值
System.out.println("key = " + key + ", value = " + value);
}
}
19.4.2. 使用forEach方法
这个forEach方法, 并不是Iterable接口中的方法。 是Map接口中定义的一个方法。 从功能上将, 与Iterable中的方法差不多。 只是在参数部分有区别。
default void forEach(BiConsumer<? super K, ? super V> action)
/**
* 2. 使用forEach进行遍历
* @param map 需要遍历的集合
*/
private static void forEach(Map<String, String> map) {
map.forEach((k, v) -> {
// k: 遍历到的每一个键
// v: 遍历到的每一个值
System.out.println("key = " + k + ", value = " + v);
});
}
19.3.3. 使用EntrySet进行遍历
Entry<K, V>:
是Map中的内部接口, 用来描述集合中的每一个键值对。
/**
* 3. 使用entrySet进行遍历
* @param map 需要遍历的集合
*/
private static void entrySet(Map<String, String> map) {
// 1. 获取一个存储有所有的Entry的一个Set集合
Set<Map.Entry<String, String>> entries = map.entrySet();
// 2. 遍历Set集合
for (Map.Entry<String, String> entry : entries) {
// 2.1. 获取键
String key = entry.getKey();
// 2.2. 获取值
String value = entry.getValue();
// 2.3. 展示
System.out.println("key = " + key + ", value = " + value);
}
}
19.5. HashMap与Hashtable的区别
- HashMap是线程不安全的集合, Hashtable是线程安全的集合。
- HashMap允许出现null键值, Hashtable是不允许的。
- HashMap的父类是AbstractMap, Hashtable的父类是Dictionary。
- HashMap的Map接口的新的实现类, 底层算法效率优于Hashtable。
19.6. 其他的实现类
- LinkedHashMap
- 与HashMap类似的,底层多维护了一个链表, 记录每一个键的存储顺序。 也就是说, 在LinkedHashMap中, 键值对的添加顺序可以得到保障。 类似于LinkedHashSet与HashSet。
- TreeMap
- 类似于TreeSet, 可以将存储进集合中的键值对, 按照键的大小比较规则, 进行升序排列。
- TreeMap的排序规则, 类似于TreeSet。
19.7. Collections工具类
19.7.1. API
19.7.2. 示例代码
package day22.dCollections;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @Description
*/
public class CollectionsUsage {
public static void main(String[] args) {
// 1. 实例化一个List集合对象
List<Integer> list = new ArrayList<>();
// 2. 添加元素
Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
// 3. 获取一个集合中的最大值,大小比较通过元素对应的类实现的Comparable接口进行比较
Integer max = Collections.max(list);
// 获取一个集合中的最大值,大小比较通过第二个参数 Comparator
Integer max2 = Collections.max(list, (i1, i2) -> i2 - i1);
// 4. 获取一个集合中的最小值,大小比较通过元素对应的类实现的Comparable接口进行比较
Integer min = Collections.min(list);
// 获取一个集合中的最小值,大小比较通过第二个参数 Comparator
Integer min2 = Collections.min(list, (i1, i2) -> i2 - i1);
// 5. 将List集合中的数据进行随机的排列(洗牌)
Collections.shuffle(list);
// 6. 交换一个List集合中两个下标对应的元素
Collections.swap(list, 0, 2);
// 7. 将一个List集合中的元素倒序排列
Collections.reverse(list);
// 8. 将一个List集合进行排序,元素的大小比较规则使用元素对应的类实现的Comparable接口进行比较大小
Collections.sort(list);
// 将一个List集合按照指定的规则进行升序排序,基本不用,List集合中本身就有这样的排序方法
Collections.sort(list, (i1, i2) -> i2 - i1);
// 9. 集合中的元素拷贝,将第二个参数集合中的数据拷贝到第一个集合中
List<Integer> copy = new ArrayList<>();
Collections.addAll(copy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
Collections.copy(copy, list);
// 10. 使用指定的数据,填充一个集合
Collections.fill(list, 0);
// 11. 将线程不安全的集合,转成线程安全的集合
// Collections.synchronizedCollection()
// Collections.synchronizedList()
// Collections.synchronizedSet()
// Collections.synchronizedMap()
}
}