Stream
什么是Stream流?
在Java 8中,得益于Lambda所带来的函数式编程,
引入了一个全新的Stream流概念 ,用于解决已有集合/数组类库有的弊端。Stream流能解决什么问题?
可以解决已有集合类库或者数组API的弊端。
Stream认为集合和数组操作的API很不好用,所以采用了Stream流简化集合和数组的操作!!小结:
Stream流是用来简化集合类库或者数组API的弊端。
Stream流其实就一根传送带,元素在上面可以被Stream流操作。
需求:从集合中筛选出所有姓张的人出来。然后再找出姓名长度是3的人。
传统写法
public class StreamDemo01 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//1.找姓张的人
List<String> Z_list = new ArrayList<>();
for (String s : list) {
if(s.startsWith("张")){
Z_list.add(s);
}
}
System.out.println(Z_list);
//2.姓名长度为3
List<String> Z_Long_list = new ArrayList<>();
for (String s : Z_list) {
if(s.length() == 3) Z_Long_list.add(s);
}
System.out.println(Z_Long_list);
}
}
Stream流写法
public class StreamDemo01 {
public static void main(String[] args) {
//需求:从集合中筛选出所有姓张的人出来。然后再找出姓名长度是3的人。
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
list.stream().filter(s -> s.startsWith("张"))
.filter(s -> s.length() == 3)
.forEach(System.out::println);
}
}
如上见得:stream基于函数式编程,更加简单!
他的限制流filter
可以链式编程,最后遍历!
Stream流的获取
Stream流式思想的核心:
先得到集合或者数组的Stream流(就是一根传送带)然后就用这个Stream流操作集合或者数组的元素。然后用Stream流简化替代集合操作的API.集合获取流的API:
(1) default Stream stream();小结:
集合获取Stream流用: stream();
数组:Arrays.stream(数组) / Stream.of(数组);
public class StreamDemo01 {
public static void main(String[] args) {
/** --------------------Collection集合获取流------------------------------- */
// Collection集合如何获取Stream流。
Collection<String> c = new ArrayList<>();
Stream<String> ss = c.stream();
/** --------------------Map集合获取流------------------------------- */
Map<String, Integer> map = new HashMap<>();
// 先获取键的Stream流。
Stream<String> keyss = map.keySet().stream();
// 在获取值的Stream流
Stream<Integer> valuess = map.values().stream();
// 获取键值对的Stream流(key=value: Map.Entry<String,Integer>)
Stream<Map.Entry<String,Integer>> keyAndValues = map.entrySet().stream();
/** ---------------------数组获取流------------------------------ */
// 数组也有Stream流。
String[] arrs = new String[]{"Java", "JavaEE" ,"Spring Boot"};
Stream<String> arrsSS1 = Arrays.stream(arrs);
Stream<String> arrsSS2 = Stream.of(arrs);
}
}
Stream的常用API
forEach : 逐一处理(遍历)
count:统计个数
– long count();
filter : 过滤元素
– Stream filter(Predicate<? super T> predicate)
limit : 取前几个元素
skip : 跳过前几个
map : 加工方法
concat : 合并流。
public class StreamDemo03 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
list.add("张三丰");
//遍历foreach
list.stream().filter(s -> s.length() == 3)
.filter(s -> s.startsWith("张"))
.forEach(System.out::println);
//统计个数count
long count = list.stream().filter(s -> s.length() == 3)
.filter(s -> s.startsWith("张")).count();
System.out.println(count);
//取前几个
list.stream().filter(s -> s.length() == 3)
.limit(2)
.forEach(System.out::println);
//跳过前几个
list.stream().filter(s -> s.length() == 3)
.skip(2)
.forEach(System.out::println);
//map方法(映射):加工方法 将原元素加工后放上去
/*将所有名称都加上小小的……*/
list.stream().map(s -> "小小的" + s).forEach(System.out::println);
/*将名称都加工成学生对象*/
//list.stream().map(s -> new Student(s)).forEach(System.out::println);
list.stream().map(Student::new).forEach(System.out::println);//构造器引用
/**
* concat合并流
*/
//数组流
Stream<Integer> s1 = Stream.of(10,20,30,40);
//集合流
Stream<String> s2 = list.stream();
//合并流 类型不同可用Object接 只能两两合并!!!!
Stream<Object> allStream = Stream.concat(s1,s2);
allStream.forEach(System.out::println);
}
}
综合案例
public class StreamDemo04 {
public static void main(String[] args) {
List<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("老子");
one.add("庄子");
one.add("孙子");
one.add("洪七公");
List<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
/**
* 1. 第一个队伍只要名字为3个字的成员姓名;
* 2. 第一个队伍筛选之后只要前3个人;
*/
Stream<String> oneStream = one.stream()
.filter(s -> s.length() == 3).limit(3);
/**
* 3. 第二个队伍只要姓张的成员姓名;
* 4. 第二个队伍筛选之后不要前2个人;
* 5. 将两个队伍合并为一个队伍;
*/
Stream<String> twoStream = two.stream()
.filter(s -> s.startsWith("张")).skip(2);
Stream<String> allStream = Stream.concat(oneStream,twoStream);
/**
* 6. 根据姓名创建`Student`对象; (加工)
* 7. 打印整个队伍的Student对象信息。
*/
allStream.map(Student::new).forEach(System.out::println);
}
}
Stream终结与非终结方法
终结方法:一旦Stream调用了终结方法,流的操作就全部终结了,不能继续使用,
只能创建新的Stream操作。
终结方法: foreach , count。非终结方法:每次调用完成以后返回一个新的流对象,
可以继续使用,支持链式编程!
public class StreamDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
list.add("张三丰");
// foreach终结方法
list.stream().filter(s -> s.startsWith("张"))
.filter(s -> s.length() == 3).forEach(System.out::println);
long count = list.stream().filter(s -> s.startsWith("张"))
.filter(s -> s.length() == 3).count();
System.out.println(count);
}
}
收集Stream流
引入:
- Stream的作用是:把集合转换成一根传送带,借用Stream流的强大功能进行的操作。但是实际开发中数据最终的形式还是应该是集合,最终Stream流操作完毕以后还是要转换成集合。这就是收集Stream流。
收集Stream流的含义:就是把Stream流的数据转回到集合中去。
Stream流:手段。
集合:才是目的。小结:
收集Stream流的含义:就是把Stream流的数据转回到集合中去。熟练函数式编程,如Lambda表达式简化函数式接口的匿名内部类形式,以及四种方法引用简化Lambda表达式,以及流式编程思想如Stream简化集合或者数组的操作。
public class StreamDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
list.add("张三丰");
Stream<String> zhangLists = list.stream().filter(s -> s.startsWith("张"));
// 把stream流转换成Set集合。
Set<String> sets = zhangLists.collect(Collectors.toSet());
System.out.println(sets);
// 把stream流转换成List集合。
Stream<String> zhangLists1 = list.stream().filter(s -> s.startsWith("张"));
List<String> lists= zhangLists1.collect(Collectors.toList());
System.out.println(lists);
// 把stream流转换成数组。
Stream<String> zhangLists2 = list.stream().filter(s -> s.startsWith("张"));
Object[] arrs = zhangLists2.toArray();
// 可以借用构造器引用申明转换成的数组类型!!!
String[] arrs1 = zhangLists2.toArray(String[]::new);
}
}