文章目录
- 1、Map集合
-
- 1.1、Map集合概述和特点
- 1.2、Map集合的基本功能
- 1.3、集合的获取功能
- 1.4、Map集合的遍历(方式1)
- 1.5、Map集合的遍历(方式2)
- 2、HashMap集合
-
- 3、TreeMap集合
-
- 3.1、TreeMap集合概述和特点
- 3.2、TreeMap集合应用案例一
- 3.3、TreeMap集合应用案例二
- 4、可变参数
-
- 4.1、可变参数
- 4.2、创建不可变集合(java9新特性)
- 5、Stream流
-
- 5.1、体验Stream流
- 5.2、Stream流的常见生成方式
- 5.3、Stream流中间操作方法
- 5.4、Stream流终结操作方法
- 5.5、Stream流的收集操作
- 5.6、Stream流综合练习
1、Map集合
1.1、Map集合概述和特点
interface Map K:键的类型;V:值的类型
- Map集合的特点
- 双列集合,一个键对应一个值
- 键不可以重复,值可以重复
- Map集合的基本使用
public class MapDemo01 {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("itheima001","林青霞");
map.put("itheima002","张曼玉");
map.put("itheima003","王祖贤");
map.put("itheima003","刘岩");
System.out.println(map);
}
}
1.2、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() |
集合的长度,也就是集合中键值对的个数 |
public class MapDemo02 {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
System.out.println(map.containsKey("郭襄"));
System.out.println(map.containsKey("郭靖"));
System.out.println(map.isEmpty());
System.out.println(map.size());
System.out.println(map);
}
}
1.3、集合的获取功能
方法名 |
说明 |
V get(Object key) |
根据键获取值 |
Set keySet() |
获取所有键的集合 |
Collection Values() |
获取所有值的集合 |
set> entrySet() |
获取所有键值对的集合 |
public class MapDemo03 {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
System.out.println(map.get("张无忌"));
System.out.println(map.get("张三丰"));
Set<String> keySet = map.keySet();
for (String key : keySet) {
System.out.println(key);
}
Collection<String> values = map.values();
for (String value : values) {
System.out.println(value);
}
}
}
1.4、Map集合的遍历(方式1)
- 遍历思路
- 我们刚才存储的元素都是成对出现的,所以我们把Map看是一个夫妻对的集合
- 把所有的丈夫给集中起来
- 遍历丈夫的集合,获取到每一个丈夫
- 根据丈夫去找对应的妻子
- 步骤分析
- 获取所有键的集合,用keySet()方法实现
- 遍历键的集合,获取到每一个键,用增强for实现
- 根据键去找值,用get(Object key)方法实现
- 代码实现
public class MapDemo01 {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
Set<String> keySet = map.keySet();
for (String key : keySet) {
String value = map.get(key);
System.out.println(key + "," + value);
}
}
}
1.5、Map集合的遍历(方式2)
- 遍历思路
- 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
- 获取所有结婚证的集合
- 遍历结婚证的集合,得到每一个结婚证
- 根据结婚证获取丈夫和妻子
- 步骤分析
- 获取所有键值对对象的集合
- set> entrySet():获取所有键值对对象
- 遍历键值对对象的集合,得到每一个键值对对象
- 根据键值对对象获取键和值
- 用getKey()得到键
- 用getValue()得到值
- 代码实现
public class MapDemo04 {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for (Map.Entry<String, String> me : entrySet) {
String key = me.getKey();
String value = me.getValue();
System.out.println(key + "," + value);
}
}
}
2、HashMap集合
2.1、HashMap集合概述和特点
- 案例需求:
- 创建一个HashMap集合,键是学生对象(Student),值是居住地(String)。存储多个元素,并遍历
- 要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
- 代码实现
学生类
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;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if(age!=student.age) return false;
return name != null ? name.equals(student.name):student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode():0;
result = 31 * result + age;
return result;
}
}
测试类
public class HashMapDemo {
public static void main(String[] args) {
HashMap<Student, String> hm = new HashMap<Student, String>();
Student s1 = new Student("林青霞", 30);
Student s2 = new Student("张曼玉", 35);
Student s3 = new Student("王祖贤", 33);
Student s4 = new Student("王祖贤", 33);
hm.put(s1,"西安");
hm.put(s2,"武汉");
hm.put(s3,"郑州");
hm.put(s4,"北京");
Set<Student> keySet = hm.keySet();
for (Student key : keySet) {
String value = hm.get(key);
System.out.println(key.getName() + "," + key.getAge() + "," + value);
}
}
}
3、TreeMap集合
3.1、TreeMap集合概述和特点
- TreeMap底层是红黑树结构
- 依赖自然排序或者比较器排序,对键进行排序
- 如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象的时候给出比较器排序规则
3.2、TreeMap集合应用案例一
- 案例需求:
- 创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String),学生属性姓名和年龄,按照年龄进行排序并遍历
- 要求按照学生的年龄进行排序,如果年龄相同则按照姓名进行排序
- 代码实现
学生类
public class Student implements Comparable<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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
int result = o.getAge() - this.getAge();
result = result == 0 ? o.getName().compareTo(this.getName()):result;
return result;
}
}
测试类
public class Test {
public static void main(String[] args) {
TreeMap<Student, String> tm = new TreeMap<>();
Student s1 = new Student("xiaohei", 23);
Student s2 = new Student("dapang", 22);
Student s3 = new Student("xiaomei", 22);
tm.put(s1,"江苏");
tm.put(s2,"北京");
tm.put(s3,"天津");
tm.forEach(
(Student key,String value)->{
System.out.println(key + "---" + value);
}
);
}
}
3.3、TreeMap集合应用案例二
- 案例需求:
- 给定一个字符串,要求统计字符串中每个字符出现的次数
- 举例:给定字符串是“aababcabcdabcde”,在控制台输出:“a(5)b(4)c(3)d(2)e(1)”
- 代码实现
import java.util.TreeMap;
public class Test2 {
public static void main(String[] args) {
String s = "aababcabcdabcde";
TreeMap<Character,Integer> tm = new TreeMap<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(!tm.containsKey(c)){
tm.put(c,1);
}else{
Integer count = tm.get(c);
count++;
tm.put(c,count);
}
}
System.out.println(tm);
tm.forEach(
(Character key,Integer value) -> {
System.out.print(key + "(" + value + ")");
}
);
}
}
4、可变参数
4.1、可变参数
- 可变参数介绍
- 可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
- 方法的参数类型已经确定,个数不确定,我们可以使用可变参数
- 可变参数定义格式
修饰符 返回值类型 方法名(数据类型...变量名){}
- 可变参数的注意事项
- 这里的变量其实是一个数组
- 如果一个方法有多个参数,包含可变参数,可变参数要放在最后
- 可变参数的基本使用
public class ArgsDemo01 {
public static void main(String[] args) {
System.out.println(sum(10, 20));
System.out.println(sum(10,20,30));
System.out.println(sum(10,20,30,40));
}
public static int sum(int... a) {
int sum = 0;
for (int i : a) {
sum += i;
}
return sum;
}
}
4.2、创建不可变集合(java9新特性)
- 方法介绍
- 在List、Set、Map接口中,都存在of方法,可以创建一个不可变的集合
- 这个集合不能添加,不能删除,不能修改
- 但是可以结合集合的带参构造,实现集合的批量添加
- 在Map接口中,还有一个OfEntriers方法可以提高代码的阅读性
- 首先会把键值对封装成一个Entry对象,再把这个Entry对象添加到集合当中
- 示例代码
public class MyVariableParmeter4 {
public static void main(String[] args) {
method1();
method2();
method3();
method4();
}
private static void method4() {
Map<String,String> map = map.ofEntries(
Map.entry("张三","苏州"),
Map.entry("李四","北京");
System.out.println(map);
);
}
private static void method3() {
Map<String,String> map = Map.of("张三","江苏","lisi","北京","wangwu","天津");
System.out.println(map);
}
private static void method2() {
Set<String> set = Set.of("a","b","c","d","a");
System.out.println(set);
}
private static void method1() {
List<String> list =List.of("a","b","c","d");
System.out.println(list);
list.add("Q");
list.remove("a");
list.set(0,"A");
System.out.println(list);
ArrayList<String> list2 = new ArrayList<>();
list2.add("aaa");
list2.add("aaa");
list2.add("aaa");
list2.add("aaa");
ArrayList<String> list3 = new ArrayList<>(List.of("a","b","c","d"));
System.out.println(list3);
}
}
5、Stream流
5.1、体验Stream流
- 案例需求:按照下面的要求完成集合的创建和遍历
- 创建一个集合,存储多个字符串元素
- 把集合中所有以“张”开头的元素存储到一个新的集合
- 把“张”开头的集合中的长度为3的元素存储到一个新的集合
- 遍历上一步得到的集合
- 原始方式示例代码
public class StreamDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
ArrayList<String> zhangList = new ArrayList<>();
for (String s : list) {
if(s.startsWith("张")){
zhangList.add(s);
}
}
System.out.println(zhangList);
ArrayList<String> threeList = new ArrayList<>();
for (String s : zhangList) {
if(s.length() == 3){
threeList.add(s);
}
}
System.out.println(threeList);
for (String s : threeList) {
System.out.println(s);
}
System.out.println("------------------");
}
}
public class StreamDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length()==3).forEach(
s -> System.out.println(s)
);
}
}
- Stream流的好处
- 直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤张姓、过滤长度为3、逐一打印
- Stream流把真正的函数式编程风格引入到Java中
- 代码简洁
5.2、Stream流的常见生成方式
- Stream流的思想
- Stream流的三类方法
- 获取Stream流
- 中间方法
- 流水线上的操作
- 一次操作完毕之后,还可以继续进行其他操作
- 终结方法
- 一个Stream流只能有一个终结方法
- 是流水线上的最后一个操作
- 生成Stream流的方式
- Collection体系集合
- 使用默认方法stream()生成流,default Stream stream();
- Map体系集合
- 数组
- 同种数据类型的多个数据
- 通过Stream接口的静态方法of(T…values)生成流
- 代码演示
import java.util.*;
import java.util.stream.Stream;
public class StreamDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<String>();
Stream<String> setStream = set.stream();
Map<String,Integer> map = new HashMap<String,Integer>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String,Integer>> entryStream = map.entrySet().stream();
String[] strArray = {"hello","hello","java"};
Stream<String> strArrayStream = Arrays.stream(strArray);
Stream<String> strArrayStream2 = Stream.of("hello","world","java");
Stream<Integer> intStream = Stream.of(10,20,30);
}
}
5.3、Stream流中间操作方法
- 概念
- 中间操作的意思是,执行完毕此方法之后,Stream流依然可以继续执行其他操作
- 常见方法
方法名 |
说明 |
Stream filter(Predicate predicate) |
用于对流中的数据进行过滤 |
Stream limit(long maxSize) |
返回此流中的元素组成的流,截取前指定参数个数的数据 |
Stream skip(long n) |
跳过指定参数个数的数据,返回由该流的剩余元素组成的流 |
static Stream concat(Stream a,Stream b) |
合并a和b两个流为一个流 |
Stream disinct() |
返回由该流的不同元素(根据Object equals(Object))组成的流 |
import java.util.ArrayList;
public class StreamDemo01 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
System.out.println("-----------");
list.stream().filter(s -> s.length()==3).forEach(s -> System.out.println(s));
System.out.println("-------------");
list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s-> System.out.println(s));
}
public class StreamDemo02 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
list.stream().limit(3).forEach(s-> System.out.println(s));
System.out.println("-----------");
list.stream().skip(3).forEach(s-> System.out.println(s));
System.out.println("----------");
list.stream().skip(2).limit(2).forEach(s-> System.out.println(s));
}
}
import java.util.ArrayList;
import java.util.stream.Stream;
public class StreamDemo03 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
Stream<String> s1 = list.stream().limit(4);
Stream<String> s2 = list.stream().skip(2);
Stream.concat(s1,s2).forEach(s-> System.out.println(s));
Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s));
}
}
5.4、Stream流终结操作方法
- 概念
- 终结操作的意思是,执行完毕此方法之后,Stream流将不再执行其他操作
- 常见方法
方法名 |
说明 |
void forEach(Consumer action) |
对流的每个元素执行操作 |
long count() |
返回此流中的元素数 |
import java.util.ArrayList;
public class StreamDemo04 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
list.stream().forEach(s-> System.out.println(s));
long count = list.stream().filter(s->s.startsWith("张")).count();
System.out.println(count);
}
}
5.5、Stream流的收集操作
- 概念
- 对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中
- 常用方法
方法名 |
说明 |
R collect(Collector collector) |
把结果收集到集合中 |
方法名 |
说明 |
public static Collector toList() |
把元素收集到List集合中 |
public static Collector toSet() |
把元素收集到Set集合中 |
public static Collector toMap(Function keyMappper,Function valueMapper) |
把元素收集到Map集合中 |
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CollectDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
Stream<String> listStream = list.stream().filter(s->s.length()==3);
List<String> names = listStream.collect(Collectors.toList());
for (String name : names) {
System.out.println(name);
}
Set<Integer> set = new HashSet<>();
set.add(10);
set.add(20);
set.add(30);
set.add(33);
set.add(35);
Stream<Integer> setStream = set.stream().filter(age -> age>25);
Set<Integer> ages = setStream.collect(Collectors.toSet());
for (Integer age : ages) {
System.out.println(age);
}
String[] strArray = {"林青霞,30","张曼玉,35","王祖贤,33","柳岩,25"};
Stream<String> arraysStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1])>28);
Map<String,Integer> map = arraysStream.collect(Collectors.toMap(s -> s.split(",")[0],s->Integer.parseInt(s.split(",")[1])));
Set<String> keySet = map.keySet();
for (String key : keySet) {
Integer value = map.get(key);
System.out.println(key + "," + value);
}
}
}
5.6、Stream流综合练习
- 案例需求
- 现在有两个ArrayList集合,分别存储6名男演员和6名女演员名称,要去完成如下的操作
- 男演员只要名字为3个字的前三人
- 女演员只要姓林的,并且不要第一人
- 把过滤后的男演员姓名和女演员姓名合并到一起
- 把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
- 演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法
- 代码实现
import java.util.ArrayList;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
ArrayList<String> manList = new ArrayList<>();
manList.add("周润发");
manList.add("成龙");
manList.add("刘德华");
manList.add("吴京");
manList.add("周星驰");
manList.add("李连杰");
ArrayList<String> womanLlist = new ArrayList<>();
womanLlist.add("林心如");
womanLlist.add("张曼玉");
womanLlist.add("林青霞");
womanLlist.add("柳岩");
womanLlist.add("林志玲");
womanLlist.add("王祖贤");
Stream<String> manStream = manList.stream().filter(s -> s.length() == 3).limit(3);
Stream<String> womanStream = womanLlist.stream().filter(s -> s.startsWith("林")).skip(1);
Stream<String> stream = Stream.concat(manStream, womanStream);
stream.map(Actor::new).forEach(p-> System.out.println(p.getName()));
System.out.println("--------------------");
Stream.concat(manList.stream().filter(s -> s.length() == 3).limit(3), womanLlist.stream().filter(s ->
s.startsWith("林")).skip(1)).map(Actor::new).forEach(p -> System.out.println(p.getName()));
}
}