一、Predicate接口
在java中,还有一个函数式接口叫做Predicate,这个接口中有一个抽象方法test,可以对一个数据进行判断,并返回结果
1、抽象方法:
boolean test(T t): 判断参数t是否合法,如果合法返回true。
默认方法:
default Predicate and(Predicate other): 将两个Predicate进行合并拼接, 结果是并且的关系
default Predicate or(Predicate other) : 将两个Predicate进行合并拼接, 结果是或者的关系
default Predicate<T> negate():取非操作。 相当于!
public class Demo01Predicate {
public static void main(String[] args) {
//调用method方法,传递lambda表达式,判断字符串hello是否以指定开头
method(s -> s.startsWith("ehe"));
}
public static void method(Predicate<String> predicate) {
boolean flag = predicate.test("hello");
System.out.println("flag:" + flag);
}
}
2、默认方法:
default Predicate and(Predicate other): 将两个Predicate进行合并拼接, 结果是并且的关系
比如:
a.test("hello"); //检查以指定字符串开头
b.test("hello"); //检查字符串的长度是否满足要求.
a.test("hello") && b.test("hello")
Predicate c = a.and(b); //将a和b合并成c, c中就包含了a和b的操作。 结果是并且的关系。 a&&b
c.test("hello"); //因为c中包含的是a和b的操作,所以相当于 a.test("hello") && b.test("hello")
public class Demo02Predicate {
public static void main(String[] args) {
method(s -> s.startsWith("hel"),
s -> s.length() == 5);
}
/*
第一个参数Predicate: 用来判断字符串"hello"是否以指定的内容开头
第二个参数Predicate: 用来判断字符串"hello"长度是否满足要求
如果字符串hello是以指定内容开头,并且长度满足要求,那么结果就是true。否则结果就是false。
*/
public static void method(Predicate<String> one, Predicate<String> two) {
/*
//用来判断字符串"hello"是否以指定的内容开头
boolean flagOne = one.test("hello");
//用来判断字符串"hello"长度是否满足要求
boolean flagTwo = two.test("hello");
//如果全部成立,那么结果才成立,所以可以使用&&进行连接
boolean flagThree = flagOne && flagTwo;
System.out.println(flagThree);
*/
//使用and方法,对两个Predicate进行合并
//Predicate<String> three = one.and(two);
//boolean flag = three.test("hello"); // 相当于 one.test("hello") && two.test("hello")
//System.out.println("flag:" + flag);
//一步到位, 合并之后直接去判断
boolean flag = one.and(two).test("hello");
System.out.println("flag:" + flag);
}
}
在Predicate中,有一个默认方法,叫做or,可以对两个Predicate进行和并,结果是或者的关系(只要一个成立,那么结果就成立)
默认方法:
default Predicate or(Predicate other) : 将两个Predicate进行合并拼接, 结果是或者的关系
public class Demo03Predicate {
public static void main(String[] args) {
method(s -> s.startsWith("hh"),
s -> s.length() == 5);
}
/*
第一个参数Predicate: 判断字符串是否以指定开头
第二个参数Predicate: 判断字符串的长度是否满足要求
只要一个满足,那么结果就是true。 此时可以使用或者的关系去表示
*/
public static void method(Predicate<String> one, Predicate<String> two) {
/*
//判断字符串是否以指定开头
boolean flagOne = one.test("hello");
//判断字符串的长度是否满足要求
boolean flagTwo = two.test("hello");
//只要满足一个,那么结果就成立
boolean flagThree = flagOne || flagTwo;
System.out.println("flagThree:" + flagThree);
*/
//使用or方法,对两个Predicate进行合并,然后调用test方法,进行判断
//Predicate<String> three = one.or(two); //将两个Predicate进行合并,结果是或者的关系
//boolean flag = three.test("hello"); //相当于one.test("hello") || two.test("hello")
//System.out.println("flag:" + flag);
//一步到位
boolean flag = one.or(two).test("hello");
System.out.println(flag);
}
}
在Predicate中还有一个默认方法,叫做negate,用于进行取非。 这个方法有一个Predicate就可以用
默认方法:
default Predicate<T> negate():取非操作。 相当于!
public class Demo04Predicate {
public static void main(String[] args) {
method(s -> s.length() == 2);
}
public static void method(Predicate<String> predicate) {
//对调用test得到的结果进行取非
boolean flag = predicate.negate().test("hello");
System.out.println("flag:" + flag);
}
}
数组当中有多条“姓名+性别”的信息如下,请通过 Predicate 接口的拼装将符合要求的字符串筛选到集合
ArrayList 中,需要同时满足两个条件:
1. 必须为女生;
2. 姓名为4个字
public class Demo05PredicateTest {
public static void main(String[] args) {
String[] array = { "迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男", "赵丽颖,女" };
method(s -> s.split(",")[1].equals("女"),
s -> s.split(",")[0].length() == 4,
array);
}
/*
定义方法,传递三个参数
第一个参数: Predicate,用来判断是否为女生
第二个参数: Predicate, 用来判断姓名是否是4个字
第三个参数: 传递数组
*/
public static void method(Predicate<String> one, Predicate<String> two, String[] array) {
//找出array这个数组中的姓名长度是4个字的女生,然后放入到集合中。
//创建集合
ArrayList<String> list = new ArrayList<>();
//遍历array数组,拿到里面的每一个元素
for(String str : array) {
/*
//通过one判断这个字符串是否是女生
boolean flagOne = one.test(str);
//用来判断姓名是否是4个字
boolean flagTwo = two.test(str);
if(flagOne && flagTwo) {
list.add(str);
}
*/
//如果one和two对于str的判断结果全部都成立,那么结果才成立
if(one.and(two).test(str)) {
list.add(str);
}
}
//打印集合
System.out.println(list);
}
}
二、Function接口
1、在java中,还有一个函数式接口叫做Function,可以把这个接口看成一个函数模型。 里面一个有一个方法叫做apply,可以接收一个参数,然后得到一个结果
抽象方法:
R apply(T t): 收到一个参数,然后得到一个结果。
比如收到一个字符串类型的"10", 可以在方法内部进行处理,变成一个int类型的10,然后再得到结果
Function<T,R>有两个泛型: 其中泛型T表示apply方法参数的数据类型, 参数R表示apply方法返回值的数据类型。
public class Demo01Function {
public static void main(String[] args) {
//method(s -> Integer.parseInt(s));
method(Integer::parseInt);
}
//使用Function的apply方法,将一个字符串类型的"10"转成一个int类型的10,并返回.
//此时就是接受一个字符串类型的参数,并的到一个int类型的结果
public static void method(Function<String, Integer> function) {
//通过Function调用apply方法,处理"10"
Integer num = function.apply("10");
System.out.println(num);
}
}
2、在Function中,还有一个默认方法,叫做andThen,可以对两个Function进行合并。
默认方法:
default Function andThen(Function after): 将两个Function进行合并。合并成一个Function。 有先后顺序。 a.andThen(b)。 结果是先a后b
举例:
Function a: 将字符串类型的是转成数字10. "10" -> 10
Function b: 将数字10加上100,变成110 10 -> 110
对a和b进行合并,合并成c
Function c: 将字符串10转成数字10,并加上100. "10" -> 10 -> 110
使用练习来将字符串10变成数字10然后加上100
public class Demo02Function {
public static void main(String[] args) {
method(s -> Integer.parseInt(s),
num -> num + 100);
}
/*
第一个参数Function:将字符串"10"变成数字10
第二个参数Function:将上步得到结果数字10加上100,变成110
*/
public static void method(Function<String, Integer> one, Function<Integer, Integer> two) {
/*
//one调用apply方法,处理字符串"10"
Integer num = one.apply("10");
//two调用apply方法,将上一步得到的结果加上100
Integer result = two.apply(num);
//打印结果
System.out.println(result);
*/
//对one和two进行合并
//先通过one调用apply方法,得到一个结果,再通过two调用apply方法,处理刚刚得到的结果。 相当于 two.apply(one.apply("10"))
Integer result = one.andThen(two).apply("10");
System.out.println(result);
}
}
3、请使用 Function 进行函数模型的拼接,按照顺序需要执行的多个函数操作为:
1. 将字符串截取数字年龄部分,得到字符串;
2. 将上一步的字符串转换成为int类型的数字;
3. 将上一步的int数字累加100,得到结果int数字
public class Demo03Function {
public static void main(String[] args) {
String str = "赵丽颖,20";
//调用method方法,传递Lambda表达式
method(s -> Integer.parseInt(s.split(",")[1]),
age -> age + 100,
str);
}
/*
参数传递两个Function和一个字符串
第一个Function参数: 用来得到整个字符串中的年龄部分,并将这个结果转成一个int数字
第二个Function参数: 用来将上一步得到的int数字加上100
第三个参数: 字符串
*/
public static void method(Function<String, Integer> one, Function<Integer, Integer> two, String str) {
/*
//通过one处理str
Integer age = one.apply(str);
//通过two处理上一步得到的结果
Integer result = two.apply(age);
System.out.println("result:" + result);
*/
//将one和two进行合并,并处理
Integer result = one.andThen(two).apply(str); //先通过one调用apply处理str,再通过two调用apply处理刚刚得到的结果
System.out.println("result:" + result);
}
}
传统方式遍历集合
1. 首先筛选所有姓张的人;
2. 然后筛选名字有三个字的人;
3. 最后进行对结果进行打印输出
public class Demo01OldPrintArrayList {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//1. 首先筛选所有姓张的人;
List<String> zhangList = new ArrayList<>();
//遍历list集合,找出所有姓张的,然后添加到zhangList集合
for(String str : list) {
if(str.startsWith("张")) {
zhangList.add(str);
}
}
//2. 基于上一步,然后筛选名字有三个字的人;
List<String> threeList = new ArrayList<>();
//遍历zhangList,得到所有三个字的人
for (String str : zhangList) {
if(str.length() == 3) {
threeList.add(str);
}
}
//3. 最后进行对结果进行打印输出
//遍历集合,逐个打印
for (String str : threeList) {
System.out.println(str);
}
}
}
传统方式遍历集合
1. 首先筛选所有姓张的人;
2. 然后筛选名字有三个字的人;
3. 最后进行对结果进行打印输出
public class Demo02NewStream {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//使用stream流操作
//Stream流初体现
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
}
}
获取流的三种方式:
1. 通过Collection单列集合获取一个流对象
2. 通过Map双列集合获取一个流对象
3. 通过数组获取一个流对象。
通过Collection单列集合获取一个流对象
在Collection中,有一个方法,叫做stream(),用来获取这个集合对应的流对象
default Stream<E> stream(): 获取集合对应的stream流对象。
public class Demo03GetStream {
public static void main(String[] args) {
//创建一个List集合
List<String> list = new ArrayList<>();
//添加元素
list.add("aaa");
list.add("bbb");
list.add("ccc");
//调用集合的stream方法,获取集合的stream流
Stream<String> stream = list.stream();
System.out.println(Arrays.toString(stream.toArray())); //将流转成数组,然后再打印内容
//创建一个Set集合
Set<String> set = new HashSet<>();
//获取此set集合对应的stream流
Stream<String> stream2 = set.stream();
}
}
通过Map集合获取Stream流对象
我们不能直接通过Map集合,获取Stream流。 我们可以通过Map集合间接的去获取
1. 先获取到Map集合中的所有的key,存放在一个Set集合中,然后获取该set集合的流
2. 先获取到Map集合中所有的value,存在一个集合。 然后获取该集合的流
3. 先获取到Map集合的所有Entry对象,存放在一个集合,然后改集合的流
public class Demo04GetStream {
public static void main(String[] args) {
//创建Map集合
Map<String, String> map = new HashMap<>();
//添加元素
map.put("it001", "jack");
map.put("it002", "rose");
map.put("it003", "tom");
//先获取到Map集合中的所有的key,存放在一个Set集合中,然后获取该set集合的流
Set<String> keys = map.keySet();
//获取该set集合的stream流
Stream<String> setStream = keys.stream();
System.out.println(Arrays.toString(setStream.toArray()));
System.out.println("==========================================");
//获取所有值的stream流
//获取map集合中所有的值
Collection<String> values = map.values();
//获取对应的流
Stream<String> valueStream = values.stream();
//打印
System.out.println(Arrays.toString(valueStream.toArray()));
System.out.println("==========================================");
//先获取到Map集合的所有Entry对象,存放在一个集合,然后改集合的流
Set<Map.Entry<String, String>> entrys = map.entrySet();
//获取此保存entry对象的Set集合的Stream流
Stream<Map.Entry<String, String>> entryStream = entrys.stream();
//打印
System.out.println(Arrays.toString(entryStream.toArray()));
}
}
通过数组获取一个流对象
1. 可以通过Stream中的静态方法of获取
static Stream of(T... values): 根据可变参数或者数组获取一个流对象
2. 可以通过Arrays工具类的stream方法获取
static <T> Stream<T> stream(T[] array): 传递一个数组得到数组对应的stream流
public class Demo05GetStream {
public static void main(String[] args) {
//创建一个数组
String[] strArr = {"aa", "bb", "cc"};
//调用Stream的静态方法of,获取对应的流
Stream<String> streamOne = Stream.of(strArr);
//打印
System.out.println(Arrays.toString(streamOne.toArray()));
//可以通过Arrays工具类的stream方法获取
Stream<String> streamTwo = Arrays.stream(strArr);
System.out.println(Arrays.toString(streamTwo.toArray()));
//小技巧,第一种方式获取流对象,参数是一个可变参数,所以也可以传递任意个参数,直接根据任意个数据获取一个流对象
//static Stream of(T... values): 根据可变参数或者数组获取一个流对象
Stream<String> streamThree = Stream.of("hello", "world", "java");
System.out.println(Arrays.toString(streamThree.toArray()));
}
}
三、Stream流
在Stream中,有一个方法叫做Filter,可以进行过滤,过滤掉不想要的内容,只留下我们想要的。
filter方法:
Stream filter(Predicate predicate): 根据规则过滤掉自己不想要的内容,只留下自己需要的。
参数Predicate用来定义过滤的规则。
回忆
Predicate这个是一个函数式接口,里面有一个抽象方法叫做test,可以判断一个数据是否符合规则。
参数是一个函数式接口,那么可以在参数位置传递lambda表达式。 这个lambda表达式表示的是
这个接口中的test方法的内容。 要在lambda表达式中定义过滤的规则, 如果返回的是true,表示
该数据留下,如果返回的是false表示该数据过滤掉。
public class Demo01StreamFilter {
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream = Stream.of("aa", "bbbbb", "ccc", "dd", "eeeee");
//对这个stream进行过滤,只留下字符串长度大于4的
Stream<String> newStream = stream.filter(s -> s.length() > 4);
//打印结果
System.out.println(Arrays.toString(newStream.toArray()));
}
}
在Stream中,有一个方法,叫做count,可以统计流中元素的个数
long count() 返回此流中的元素数。
public class Demo02StreamCount {
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream = Stream.of("aa", "bb", "cc");
//获取这个流中元素的个数
long count = stream.count();
//打印结果
System.out.println(count);
}
}
在Stream中,有一个方法,叫做limit,可以获取流中前n个元素
Stream<T> limit(long maxSize):参数maxSize表示要获取前几个。但是结果不能超过原来流的所有元素个数.
public class Demo03StreamLimit {
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream = Stream.of("aa", "bb", "cc", "dd", "ee");
//调用limit方法,获取流中的前3个元素
Stream<String> newStream = stream.limit(3);
//打印newStream
System.out.println(Arrays.toString(newStream.toArray()));
}
}
在Stream中,有一个方法,可以跳过流中的前几个元素这个方法叫做skip
Stream<T> skip(long n): 跳过流中的前n个元素
public class Demo04StreamSkip {
public static void main(String[] args) {
//获取一个流
Stream<String> stream = Stream.of("aa", "bb", "cc", "dd", "ee");
//跳过流中的前三个元素,把其他元素放到新的流中国
Stream<String> newStream = stream.skip(3);
//打印新的流中的内容
System.out.println(Arrays.toString(newStream.toArray()));
}
}
在Stream中有一个方法,叫做map,可以将一个流中的数据映射到另一个流中。映射的过程中,数据可以有一些改变。
比如:
原来的流中的内容: "10", "20", "30"
映射之后,可以把每一个字符串变成数字放入到新的流中: 10, 20, 30
通俗来说,就是将原来流中的每一个元素都进行指定的操作,然后放入到一个新的流中。
Stream map(Function mapper): 用来将一个流中的元素映射到另一个流中。参数Function是映射的规则
回忆Function:
Function里面有一个抽象方法apply,可以对一个数据进行处理,然后得到对应的结果。
map方法的参数就是一个Function,所以要使用这个参数Function定义映射规则。
map方法的作用是将原来流中的每一个元素都进行制定的操作放入到新的流,要进行什么操作。
就在Function中的apply方法中定义规则即可。
参数是Function函数式接口,所以可以传递Lambda表达式,可以在lambda表达式中定义规则
public class Demo05StreamMap {
public static void main(String[] args) {
//将保存字符串的stream流中的元素映射到保存数字的流中
Stream<String> stream = Stream.of("11", "22", "33");
//进行映射,映射到保存数字的集合中。也就是把流中的每一个元素转成数字,放入到新的流
//Stream<Integer> stream2 = stream.map(str -> Integer.parseInt(str));
Stream<Integer> stream2 = stream.map(Integer::parseInt);
//打印stream2中的内容
System.out.println(Arrays.toString(stream2.toArray()));
}
}
在Stream中,有一个静态方法,可以将两个流合并为一个流
static Stream concat(Stream a, Stream b):将a和b两个流进行合并,并返回合并后的流
public class Demo06StreamConcat {
public static void main(String[] args) {
//获取一个流
Stream<String> one = Stream.of("aa", "bb");
//再获取一个流
Stream<String> two = Stream.of("cc", "dd");
//对这两个流合并
Stream<String> three = Stream.concat(one, two);
//打印
System.out.println(Arrays.toString(three.toArray()));
}
}
在Stream中有一个方法,叫做foreach,可以对流中的元素进行逐一处理
void forEach(Consumer action): 对流中的元素进行逐一处理
回忆Consumer
Consumer是一个消费者,可以消费一个数据。 拿到这个数据对这个数据进行处理。
void accept(T t): 用来对参数t进行处理。
foreach中的参数Consumer用来绝对怎么处理流中的每一个元素。 因为Consumer中的accept方法
就是用来对数据进行消费处理的。
public class Demo07StreamForeach {
public static void main(String[] args) {
//获取一个流对象
Stream<String> stream = Stream.of("aa", "bb", "cc", "dd");
//对流中的元素进行逐一处理(把每一个元素转成大写,然后打印)
stream.forEach(s -> System.out.println(s.toUpperCase()));
}
}
现在有两个 ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以
下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名;
2. 第一个队伍筛选之后只要前3个人;
3. 第二个队伍只要姓张的成员姓名;
4. 第二个队伍筛选之后不要前2个人;
5. 将两个队伍合并为一个队伍;
6. 根据姓名创建 Person 对象;
7. 打印整个队伍的Person对象信息。
两个队伍(集合)的代码如下
public class Demo08StreamTest {
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("洪七公");
one.add("欧阳锋");
List<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
//1. 第一个队伍只要名字为3个字的成员姓名;
List<String> oneA = new ArrayList<>();
for (String s : one) {
if(s.length() == 3) {
oneA.add(s);
}
}
//2. 第一个队伍筛选之后只要前3个人;
List<String> oneB = new ArrayList<>();
//因为筛选前三个,所以可以使用循环执行三次
for(int i = 0; i < 3; i++) {
String name = oneA.get(i);
oneB.add(name);
}
//3. 第二个队伍只要姓张的成员姓名;
List<String> twoA = new ArrayList<>();
//遍历two集合,拿到姓张的添加到twoA中
for(String s : two) {
if(s.startsWith("张")) {
twoA.add(s);
}
}
//4. 第二个队伍筛选之后不要前2个人;
List<String> twoB = new ArrayList<>();
//遍历twoA, 跳过前两次
for(int i = 2; i < twoA.size(); i++) {
String name = twoA.get(i);
twoB.add(name);
}
//5. 将两个队伍合并为一个队伍;
List<String> totalList = new ArrayList<>();
totalList.addAll(oneB);//将oneB中的所有元素添加到totalList
totalList.addAll(twoB);
//6. 根据姓名创建 Person 对象;放入到一个新的集合中
List<Person> personList = new ArrayList<>();
//遍历totalList集合,拿到里面的每一个姓名,根据这个姓名创建Person对象,添加到personList
for (String name : totalList) {
personList.add(new Person(name));
}
//7. 打印整个队伍的Person对象信息。
for (Person p : personList) {
System.out.println(p);
}
}
}
使用Stream流的方式处理集合
下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名;
2. 第一个队伍筛选之后只要前3个人;
3. 第二个队伍只要姓张的成员姓名;
4. 第二个队伍筛选之后不要前2个人;
5. 将两个队伍合并为一个队伍;
6. 根据姓名创建 Person 对象;(根据所有的姓名创建Person对象并存在一个新的容器中)
7. 打印整个队伍的Person对象信息。
两个队伍(集合)的代码如下
public class Demo09StreamTest {
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("洪七公");
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> streamOne = one.stream().filter(s -> s.length() == 3).limit(3);
//3. 第二个队伍只要姓张的成员姓名;
//4. 第二个队伍筛选之后不要前2个人;
Stream<String> streamTwo = two.stream().filter(s -> s.startsWith("张")).skip(2);
//5. 将两个队伍合并为一个队伍;
Stream<String> totalStream = Stream.concat(streamOne, streamTwo);
//6. 根据姓名创建 Person 对象;(根据所有的姓名创建Person对象并存在一个新的容器中。将原来流中的元素映射到新的流中)
//7. 打印整个队伍的Person对象信息。
totalStream.map(Person::new).forEach(System.out::println);
}
}
Stream流的注意事项
1. Stream中的非终结方法,都有一个返回值,返回值为本身Stream类型。 但是返回值不是调用者对象
2. Stream流对象只能一次性使用。 不能多次使用
public class Demo10Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("aa", "bb", "cc");
Stream<String> stream2 = stream.limit(2);
//System.out.println(stream == stream2);
stream.skip(3); //Stream流对象只能一次性使用。 不能多次使用
}
}
如果使用之前的Stream流对象进行并发操作,会有问题,于是说就有了并发流,支持并发操作。
如何获取并发流:
1. 通过普通流对象调用parallel() 获取一个并发流对象
S parallel(): 获取一个并发流
2. 通过集合,直接调用parallelStream方法获取一个并发流
Stream<E> parallelStream():获取一个并发流
public class Demo11ParallelStream {
public static void main(String[] args) {
method2();
}
//通过集合,直接调用parallelStream方法获取一个并发流
public static void method2() {
//创建一个集合
List<String> list = new ArrayList<>();
list.add("张三丰");
list.add("宋远桥");
list.add("张无忌");
list.add("张翠山");
//直接调用parallelStream方法获取一个并发流
Stream<String> stream = list.parallelStream();
//对流中的每一个元素进行逐一打印
stream.forEach(System.out::println);
}
//通过普通流对象调用parallel() 获取一个并发流对象
public static void method1() {
//获取一个普通流对象
Stream<String> stream = Stream.of("张三丰", "宋远桥", "张无忌", "张翠山");
//获取这个普通流对应的并发流
Stream<String> parallelStream = stream.parallel();
//对并发流中的每一个元素进行逐一处理(打印)
//parallelStream.forEach(System.out::println); //并发流逐一处理是无序的。
parallelStream.forEachOrdered(System.out::println);//如果要有序,可以使用forEachOrdered方法进行逐一处理,但是这个方法会极大的牺牲效率
}
}