1.stream流的意义
- 与相同功能的操作相比,Stream流的代码量小,代码更高级。
- Stream流在面向大的数据时,执行效率更高。
- 使用Stream流的操作时不占用存储(原因是stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成)。
- Stream流的思想大致可以理解为一条流水线,经过我们规定的方式去加工产品,经过多道工序后,最终就得到了我们想要的最终产品。
2.不同集合或数据存储类型获取Stream流方法
-
单列集合
- 使用Collection类(单列集合的父接口)的默认方法 stream()
-
public class getStream { public static void main(String[] args) { //单列集合 获取stream流的方法 //使用Collection类(单列集合的父接口)的默认方法 ArrayList<String> list = new ArrayList<>(); list.add("张三"); list.add("张无忌"); list.add("赵敏"); list.add("周芷若"); list.add("金毛狮王"); list.add("张三丰"); list.add("李连杰"); list.stream().forEach(name -> System.out.println(name)); } }
双列集合
-
双列集合不能直接使用stream流,只能通过间接的方式来使用,比如它的keyset,value,entrySet来使用
-
public class getStream { public static void main(String[] args) { //双列集合 keyset,value,entrySet 来使用stream流 HashMap<String, String> map = new HashMap<>(); map.put("张三","上海"); map.put("李四","北京"); map.put("王五","重庆"); map.keySet().stream().forEach(key -> System.out.println(key+"=="+map.get(key))); map.values().stream().forEach(value -> System.out.println(value)); map.entrySet().stream().forEach(entry -> System.out.println(entry)); } }
数组和杂乱数据
- 数组一般使用数组工具类Arrays中的stream()方法来获取流,也可以使用Stream接口的静态方法of()来获取流(这种方法实质上也是第一种方法)
public class getStream {
public static void main(String[] args) {
//数组
int[] nums = {1,2,3,4,5};
// Arrays.stream(nums).forEach(num -> System.out.println(num));
//如果是基本数据类型数组 则存的是整体
Stream.of(nums).forEach(num -> System.out.println(num));
Stream.of("1","2","3").forEach(num -> System.out.println(num));
}
}
3.Stream流中的方法
Stream流中的方法分为两种 中间方法 和 终结方法
中间方法
中间方法返回新的Stream流,原来的Stream流只能用一次,建议使用链式编程。只会修改流中的数据,并不会影响到集合或数组原有的数据。
public class middleStream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("张无忌");
list.add("赵敏");
list.add("周芷若");
list.add("金毛狮王");
list.add("张三丰");
list.add("李连杰");
//filter
//可以使用匿名内部类 和 lambda两种方式
System.out.println("============filter===========");
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.startsWith("张");
}
}).forEach(name -> System.out.println(name));
System.out.println("=======================");
list.stream().filter(name -> name.startsWith("张")).forEach(name -> System.out.println(name));
System.out.println("==========skip=============");
//limit 获取前几个
//skip 跳过前几个
list.stream().limit(3).forEach(name -> System.out.println(name));
System.out.println("=======================");
list.stream().skip(3).forEach(name -> System.out.println(name));
//distinct 去重
//底层是equals + hashcode 所以 如果集合里面存的是对象 需要重新方法
System.out.println("=========distinct========");
list.add("张无忌");
System.out.println(list);
list.stream().distinct().forEach(name -> System.out.println(name));
//concat 合并两个流
System.out.println("=========concat========");
ArrayList<Object> list1 = new ArrayList<>();
list1.add("孙悟空");
list1.add("猪八戒");
Stream.concat(list.stream(),list1.stream()).forEach(name -> System.out.println(name));
//map 转换流中的数据类型
System.out.println("=========map========");
ArrayList<String> list2 = new ArrayList<>();
list2.add("1");
list2.add("2");
list2.add("3");
//使用匿名内部类
// list2.stream().map(new Function<String, Integer>() {
// @Override
// public Integer apply(String s) {
// return Integer.parseInt(s);
// }
// }).forEach(num -> System.out.println(num));
//lambda
list2.stream().map(num -> Integer.parseInt(num)).forEach(num -> System.out.println(num.getClass()));
}
}
终结方法
public class middleStream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("张无忌");
list.add("赵敏");
list.add("周芷若");
list.add("金毛狮王");
list.add("张三丰");
list.add("李连杰");
//forEach 遍历
list.stream().forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
System.out.println("==============");
list.stream().forEach(s -> System.out.println(s));
//count 统计
System.out.println(list.stream().count());
//toArray 收集流中的数据 放到数组中
String[] array = list.stream().toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int value) {
return new String[value];
}
});
Arrays.stream(array).forEach(s -> System.out.println(s));
System.out.println("=========");
String[] array1 = list.stream().toArray(value ->
new String[value]);
Arrays.stream(array1).forEach(s -> System.out.println(s));
}
}
collect:
public class stream_collect {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张无忌-男-20","周芷若-女-18","张翠山-男-40","张三丰-男-80","赵敏-女-23");
//收集所有的男性
//方式1
list.stream().filter(s -> "男".equals(s.split("-")[1])).forEach(s -> System.out.println(s));
System.out.println("==============");
//方式2 收集到list
List<String> myList = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toList());
System.out.println(myList);
System.out.println("==============");
//方式3 收集到Set
Set<String> mySet = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toSet());
System.out.println(mySet);
//方式4 收集到Map 需要注明键值的规则
//参数1 键的生成规则 参数2 值的生成规则
//匿名内部类的方式
//Function<泛型1,泛型2> 泛型1是流中的数据类型 泛型2是目标键(值)的类型
System.out.println("==============");
Map<String, Integer> map = list.stream().filter(s -> "男".equals(s.split("-")[1])).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("-")[2]);
}
}));
System.out.println(map);
//lambda表达式的方式
System.out.println("=============lambda=========");
Map<String, Integer> myMap = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toMap(
s -> s.split("-")[0],
v -> Integer.parseInt(v.split("-")[2])
));
System.out.println(myMap);
}
}
总结:
经过本次针对于Stream流的学习,加深了我对Stream流的理解,使用Stream流也更加熟练。在此之前,我只是简简单单的调用其方法大致了解含义,甚至不是很理解为什么要这么做,对一些稍微复杂的Stream流操作也看不懂。所以,这次学习是非常有必要的,我深刻的感受到了Stream流的强大,以后很多集合数组操作,Stream流必然成为我的首选。