Lambda表达式
Stream流往往结合Lambda表达式使用,学习Stream流之前先介绍下Lambda表达式。
作用:简化匿名内部类书写
细节
- 只能简化函数式接口的匿名内部类写法
- 函数式接口:有且只有一个抽象方法的接口,可在接口上方加
@FunctionalInterface
注解做标记
好处
写的代码更加简洁,让我们更加关注于方法体
省略写法
可推导可省略
- 参数类型可以省略
- 如果参数只有一个,括号也可以省略不写
- 如果方法体只有一行,大括号,return,分号都可以省略不写,但还要同时省略
//匿名内部类写法
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
//Lambda标准写法
Arrays.sort(arr,(Integer o1,Integer o2) ->{
return o2 - o1;
});
//省略写法
Arrays.sort(arr,(o1,o2) -> o2 - o1);
遍历集合
default修饰符:当没有明确访问修饰符时,默认修饰符为default
默认方法,变量,类,只能在同一个包内被访问
任意集合类型通用
default void forEach(Consumer<? super T> action);
/**
* 底层原理:
* forEach方法底层也会遍历集合,并将遍历的结果传给实现Consumer接口的对象中的accept方法
* 所以直接打印accept方法参数即可
*/
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
Stream流
结合Lambda表达式,用来简化数组,集合的操作
关于对Stream流的理解,可以把他当成工厂中的流水线,每个stream流的操作过程遵循着创建 -->操作 -->获取结果的过程,就像流水线上的节点一样组成一条条线。
使用步骤
- 获取Stream流(流水线),并把数据放上去
- 使用中间方法对Stream流进行操作
- 使用终结方法对Stream流进行操作
获取Stream流
public class Demo0 {
public static void main(String[] args) {
//单列集合
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"aaa","bbb","ccc");
list.stream().forEach(s -> System.out.println(s));
//双列集合
//双列集合不能直接获取Stream流,所以须想办法通过单列集合来获取
HashMap<String,String> map = new HashMap<>();
map.put("aaa","111");
map.put("bbb","222");
map.put("ccc","333");
//第一种方式:获取键集合
map.keySet().stream().forEach(s -> System.out.println(map.get(s)));
//第二种方式:获取键值对集合
map.entrySet().stream().forEach(entry -> System.out.println(entry));
//数组
//使用Arrays中的静态方法stream()
int[]arr = {2,345,2134,121};
Arrays.stream(arr).forEach(num -> System.out.println(num));
//散装的数据
//使用Stream的静态方法of
//方法形参是个可变参数,可以传递数组也可以传递零散的数据
//但只能传递引用数据类型数组,如果传递基本数据类型数组,会将其看做一个整体,放到Stream中
Stream.of("sfd","sfdsfs","dop").forEach(s -> System.out.println(s));
}
}
使用中间方法
细节
- 修改Stream流中的数据不会对原来的数组或集合造成影响
- 返回的是一个新的Stream流,原来的Stream流只能使用一次,可使用链式编程
public class Demo1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"aaa","abcd","jfdfs","abh");
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
//返回值为true留下,返回值为false过滤掉
return s.startsWith("a");
}
}).forEach(s -> System.out.println(s));
list.stream().filter(s -> s.startsWith("a"));
System.out.println("----------");
//获取前几个元素
list.stream().limit(3).forEach(s -> System.out.println(s));
System.out.println("------------");
//跳过前几个元素
list.stream().skip(2).forEach(s -> System.out.println(s));
System.out.println("---------");
ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list2,"aaa","sss","aaa","fds");
//元素去重
//底层用的是HashSet依赖hashSet和equals方法
list2.stream().distinct().forEach(s -> System.out.println(s));
System.out.println("-------");
//将两个流合并成一个
//尽量保证两个流的数据类型相同,如果不同合并后流的数据类型为两数据类型的共同父类
Stream.concat(list.stream(),list2.stream()).forEach(s -> System.out.println(s));
System.out.println("-----------");
ArrayList<String> list3 = new ArrayList<>();
Collections.addAll(list3,"a-12","bb-23","yu-89","iu-23");
//map:转换流中的数据类型
//第二个泛型和方法的返回值类型是要转换的数据类型
list3.stream().map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s.split("-")[1]);
}
}).forEach(num -> System.out.println(num));
list3.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(num -> System.out.println(num));
}
}
使用终结方法
public class Demo2 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"sd","aaa","sdf","sss");
//遍历
list.stream().forEach(s -> System.out.println(s));
//统计数量
long count = list.stream().count();
System.out.println(count);
System.out.println("-----------");
//收集流中的数据放到数组中
Object[] objects = list.stream().toArray();
System.out.println(Arrays.toString(objects));
System.out.println("------------");
//指定数组数据类型
//泛型为指定类型的数组
//apply方法参数:流中数据的个数 方法体:创建指定类型数组
//toArray方法底层,将流中数据依次放入创建好的数组中,返回值为装着流中所有数据的数组
String[] arr = list.stream().toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int value) {
return new String[value];
}
});
System.out.println(Arrays.toString(arr));
}
}
public class Demo3 {
public static void main(String[] args) {
String[]arr = {"aaa-111","bbb-222","ccc-333","lll-444","ddd-555"};
//Collectors.toList():创建集合,collect方法再将流中数据放入集合中
//Collectors:是Stream流中的工具类
List<String> list = Arrays.stream(arr).collect(Collectors.toList());
System.out.println(list);
Set<String> set = Arrays.stream(arr).collect(Collectors.toSet());
System.out.println(set);
/**
* toMap参数1:键的生成规则
* 泛型1:流中数据类型
* 泛型2:键的数据类型
*
* 方法形参:流中数据
* 方法体:处理流中数据生成键的代码
* 返回值:键
* toMap参数2:值的生成规则
* 同理
*
* 键不能重复,否则会报异常
*/
Map<String, Integer> map = Arrays.stream(arr).collect(Collectors.toMap(new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[0];
}
}, new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s.split("-")[1]);
}
}));
System.out.println(map);
}
}