经常会遇到这种情况,想去整理一些东西,网上一看,已经有网友整理了,而且整理的还挺好,自己就懒得再去整理,而且工作中真正用到时,上网一搜,一般就能解决自己遇到的问题,于是就更不想去整理了…从大一到研究生毕业,接触计算机好多年了,但去年才真正开始写博客,期间有过多次这样的挣扎.今天又是从这种挣扎中走来,于是特意提醒一下自己,就算别人整理了,就算自己可能写的很差,但至少我没有让这段时间白白荒废掉,而且确实更加明白了自己要整理的东西…
下面的代码可以分成两个部分,上半部分是关于map的,由于map相对比较简单,所以栗子相对较少,flatMap一开始理解起来可能不是很容易理解,于是我用了三个栗子来帮助大家进行理解,大家需要着重理解为什么map不行以及flatMap的扁平化处理.看完之后多写写,相信大家肯定能明白flatMap的用法.
package com.nrsc.stream;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 玩具类
*/
class Toy {
private String name;
private String Color;
public Toy(String name, String color) {
this.name = name;
Color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return Color;
}
public void setColor(String color) {
Color = color;
}
@Override
public String toString() {
return "Toy{" +
"name='" + name + '\'' +
", Color='" + Color + '\'' +
'}';
}
}
/**
* 用户类
*/
class User {
private String name;
private int age;
private List<Toy> toys;
private Toy[] toyArray;
public Toy[] getToyArray() {
return toyArray;
}
public void setToyArray(Toy[] toyArray) {
this.toyArray = toyArray;
}
public List<Toy> getToys() {
return toys;
}
public void setToys(List<Toy> toys) {
this.toys = toys;
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
}
public class StreamStatus {
public static void main(String[] args) {
String myAngry = "My code was changed by my colleague again. I was very angry.";
/**
* Ⅰ map 和 mapToInt/mapToLong/mapToDouble
* 功能:map相对比较简单就是
* 取出流中的数据分别对其进行做相应的操作-----和python里的map差不多
*/
/** map输入类型为流中类型,输出类型任意*/
Stream.of(myAngry.split(" ")).map(s -> s + "||").forEach(System.out::print);
System.out.println("====================");
/** mapToInt 输入类型为流中类型,输出类型只能为int ---- mapToLong/mapToDouble同理*/
Stream.of(myAngry.split(" ")).mapToInt(s -> {
System.out.print(" // ");
return s.length();
}).forEach(System.out::print);
System.out.println("+++++++++++++++++++++");
/**
* Ⅱ flatMap
*
*/
System.out.println("=======================flatMap===========================");
System.out.println("========================栗子1============================");
/**
* 栗子1
* --------对于字符串数组而言,每个字符串又可以看成若干字母组成的集合,
* --------该如何由字符串数组直接获取到这些字母的集合呢?
*/
String[] language = {"java", "python", "matlab", "ruby", "php", "go"};
/** 或许你会想到如下的表达式
* 但是仔细分析一下,就可以知道,该表达式获取到的是每个单词字母数组的集合*/
Arrays.stream(language).map(s -> s.split("")).collect(Collectors.toList());
//验证如下
Stream<String[]> stream = Arrays.stream(language).map(s -> s.split(""));
List<String[]> list = Arrays.stream(language)
.map(s -> s.split("")).collect(Collectors.toList());
for (String[] strings : list) {
for (String string : strings) {
System.out.println(string);
}
}
/**
* 此时你就可以使用flatMap,
* ★★需要注意的是★★
* 假设flatMap中的lambda表达式为 A -> B
* 那么A应该是一个集合, 或者说 可以看作集合的参数,B是由A产生的一个Stream流
* 同时JDK会将所有流入flatMap的集合产生的Stream流合并成一个大的Stream流,然后才会离开flatMap
* ---------扁平化处理 (如果没理解,可以看文中的插图)
*/
// ★ ★ ★list2_1与list2_2等价(当输入参数为1个时一般都可以使用方法引用来代替箭头表达式) ★ ★ ★
/** 方式1*/
List<String> list2_1 = Arrays.stream(language).map(s -> s.split(""))
.flatMap(s -> Arrays.stream(s)).collect(Collectors.toList());
List<String> list2_2 = Arrays.stream(language).map(s -> s.split(""))
.flatMap(Arrays::stream).collect(Collectors.toList());
/** 方式2*/
List<String> list3 = Arrays.stream(language)
.flatMap(s -> Arrays.stream(s.split(""))).collect(Collectors.toList());
/** 方式3 注意下面这种方式要进行装箱操作,且该表达式获取到的是每个字母ASCII码值的集合*/
List<Integer> list4 = Arrays.stream(language)
.flatMap(s -> s.chars().boxed()).collect(Collectors.toList());
/**
* 栗子2
* ----对于一句英文来说,可以将其看作是若干单词组成的一个集合,
* 而每个单词又可以看成一个由若干字母组成的集合
*
* 那么求一句话中出现的所有不包括空格的字母,就可以按照如下的方式进行书写
*/
System.out.println("========================栗子2============================");
Stream.of(myAngry.split(" ")).flatMap(s -> s.chars().boxed()).distinct()
.forEach(i -> System.out.print((char) i.intValue()));
System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&");
/** 或者如下的方式*/
Stream.of(myAngry.split(" ")).map(s -> s.split(""))
.flatMap(Arrays::stream).distinct().forEach(System.out::print);
System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%");
/**
* 栗子3:
* 假设有多个用户,每个用户又有若干个玩具,这些玩具有名字和颜色两个属性,
* 那么如何通过Stream流直接由用户列表获取到所有用户的所有玩具的颜色呢?
*
*/
System.out.println("========================栗子3============================");
/**
* 数组 -----
* ★★★★★注意★★★★★
* 如果在flatMap中的lambda表达为A->B
* 如果A是集合,B(由A产生的Stream流)需要按照集合的方式创建 --- > 集合实体.Stream 集合实体.parallelStream
* 如果A是数组,BB(由A产生的Stream流)需要按照数组的方式创建----> Arrays. Stream.等
*/
User one = new User("阿大", 18);
User two = new User("阿二", 16);
User three = new User("阿三", 14);
one.setToyArray(new Toy[]{new Toy("熊大", "棕色"), new Toy("黑猫警长", "黑白色")});
two.setToyArray(new Toy[]{new Toy("手枪", "黑色"), new Toy("小汽车", "红色")});
three.setToyArray(new Toy[]{new Toy("不倒翁", "黄色"), new Toy("铁环", "灰色")});
User[] userArray = {one, two, three};
Arrays.stream(userArray).map(User::getToyArray)
.flatMap(Arrays::stream).map(Toy::getColor).forEach(System.out::println);
System.out.println("");
Stream.of(userArray).map(User::getToyArray)
.flatMap(Arrays::stream).map(Toy::getColor).forEach(System.out::println);
System.out.println("-------------------------------------------------------------------------------------");
/**
* 集合
*/
List<User> userList = Arrays.asList(one, two, three);
one.setToys(Arrays.asList(new Toy("熊大", "棕色"), new Toy("黑猫警长", "黑白色")));
two.setToys(Arrays.asList(new Toy("手枪", "黑色"), new Toy("小汽车", "红色")));
three.setToys(Arrays.asList(new Toy("不倒翁", "黄色"), new Toy("铁环", "灰色")));
userList.stream().map(User::getToys)
.flatMap(toy -> toy.stream()).map(Toy::getColor).forEach(System.out::println);
System.out.println("=====================================================================================");
userList.stream().map(User::getToys)
.flatMap(Collection::stream).map(Toy::getColor).forEach(System.out::println);
System.out.println("===================================并行流=============================================");
userList.stream().map(User::getToys)
.flatMap(toy -> toy.parallelStream()).map(Toy::getColor).forEach(System.out::println);
}
}