获取stream流的两种方式
1、根据Collection
获取
2、Stream
中静态方法of
获取
基本数据类型数组不可以获取stream
流
stream常用方法,有终结方法不再调用,非终结方法可以继续调用
终结方法:forEach、count
非终结方法:filter、limit、skip、map、sorted、distinct、match、find、max、reduce、mapToInt、concat
注意事项
1、stream流只能操作一次
2、stream方法返回的是新流
3、stream不调用终结方法,终结的操作不会执行
List list = new ArrayList<>();
Collections.addAll(list, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");
forEach
list.stream().forEach((String str) -> {
System.out.println(str);
});
list.stream().forEach(str -> System.out.println(str));
list.stream().forEach(System.out::println);
count
long count = list.stream().count();
System.out.println("count = " + count);
filter
得到名字长度为3个字的人(过滤)
list.stream().filter((String s) -> {
return s.length() == 3;
}).forEach(System.out::println);
list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
limit
获取前三个数据
list.stream().limit(3).forEach(System.out:println);
skip
跳过前2个数据
list.stream().skip(2).forEach(System.out::println);
map
将Stream
流中的字符串转换为Integer
map
可以将一种类型的流转换为另一种类型的流
Stream original = Stream.of("11", "22", "33");
Stream stream = original.map((String s) -> {
return Integer.parseInt(s);
});
original.map(s -> Integer.parseInt(s)).forEach(System.out::println);
original.map(Integer::parseInt).forEach(System.out::println);
sorted
将数据排序
无参按照默认排序,有参自定义排序
Stream stream = Stream.of(33, 22, 11, 55);
stream.sorted().forEach(System.out::println);
stream.sorted((Integer i1, Integer i2) -> {
return i2 - i1;
}).forEach(System.out::println);
stream.sorted((i1, i2) -> i2 - i1).forEach(System.out::println);
distinct
对数字去重
Stream stream = Stream.of(22, 33, 22, 11, 33);
stream.distinct().forEach(System.out::println);
对字符串去重
Stream stream = Stream.of("aa", "bb", "aa", "bb", "cc");
stream.distinct().forEach(System.out::println);
对自定义对象去重
在person
类中重写equals
和hashCode
方法就可以去重了
Stream personStream = Stream.of(
new Person("貂蝉", 18),
new Person("杨玉环", 20),
new Person("杨玉环", 20),
new Person("西施", 16),
new Person("西施", 16),
new Person("王昭君", 25));
personStream.distinct().forEach(System.out::println);
match
allMatch
匹配所有元素,所有都需要满足条件
Stream stream = Stream.of(5, 3, 6, 1);
boolean b = stream.allMatch((Integer i) -> {
return i > 5;
});
boolean b1 = stream.allMatch(i -> i > 5);
System.out.println(b); // false
anyMatch
匹配某个元素,只要有一个满足条件即可
boolean b2 = stream.anyMatch(i -> i > 5);
System.out.println(b2); // true
noneMatch
匹配所有元素,所有都不满足条件
boolean b3 = stream.noneMatch(i -> i < 5);
System.out.println(b3); // false
find
Stream stream = Stream.of(33, 11, 22, 5);
Optional first = stream.findFirst();
System.out.println(first.get());
Optional any = stream.findAny();
System.out.println(any.get());
max
Stream stream = Stream.of(5, 3, 6, 1);
// 1 3 5 6
Optional max = stream.max((o1, o2) -> o1 - o2);
System.out.println(max.get()); // 取出最后一个
min
Stream stream = Stream.of(5, 3, 6, 1);
// 1 3 5 6
Optional min = stream.min((o1, o2) -> o1 - o2);
System.out.println(min.get()); // 取出第一个
reduce
将数据归纳得到一个数据
// 将数据归纳得到一个数据
Stream stream = Stream.of(4, 5, 3, 9);
// 第一个参数identity:默认值
// 第二个参数accumulator:对数据进行处理的方式
// reduce如何执行
// 第一次,将默认值赋值给x,取出集合第一个元素赋值给y
// 第二次,将上一次返回的结果赋值x,取出集合第二个元素赋值给y
// 第三次,将上一次返回的结果赋值x,取出集合第三个元素赋值给y
// 第四次,将上一次返回的结果赋值x,取出集合第四个元素赋值给y
int reduce = stream.reduce(0, (x, y) -> {
System.out.println("x = " + x + ", y = " + y);
return x + y;
});
System.out.println(reduce); // 21
// 获取最大值
Integer max = stream.reduce(0, (x, y) -> {
return x > y ? x : y;
});
System.out.println(max); // 9
map和reduce组合
// 求出所有年龄的总和
Stream stream = Stream.of(
new Person("刘德华", 58),
new Person("张学友", 56),
new Person("郭富城", 54),
new Person("黎明", 52)
);
// 得到所有年龄,然后求和
Integer totalAge = stream.map(p -> p.getAge()).reduce(0, (x, y) -> x + y);
System.out.println(totalAge);
Integer totalAge1 = stream.map(p -> p.getAge()).reduce(0, Integer::sum);
// 找出最大年龄
Integer maxAge = stream.map(p -> p.getAge()).reduce(0, (x, y) -> x > y ? x : y);
System.out.println(maxAge);
Integer maxAge1 = stream.map(p -> p.getAge()).reduce(0, Math::max);
// 统计a出现的次数
Stream stream1 = Stream.of("a", "c", "b", "a", "b", "a");
Integer count = stream1.map(s -> {
if (s == "a") {
return 1;
} else {
return 0;
}
}).reduce(0, Integer::sum);
System.out.println(count);
mapToInt
Integer
占用内存比int
多,在Stream
流中要进行装箱拆箱耗性能
Stream stream = Stream.of(1, 2, 3, 4, 5);
// 把大于3的打印出来
stream.filter(n -> n > 3).forEach(System.out::println);
// IntStream:内部操作的是int类型的数据,可以节省内存,减少自定装箱拆箱
IntStream intStream = stream.mapToInt((Integer n) -> {
return n.intValue();
});
IntStream intStream = stream.mapToInt(Integer::intValue);
intStream.filter(n -> n > 3).forEach(System.out::println);
concat
将两个流合并成一个流,使用静态方法concat
Stream streamA = Stream.of(“张三”);
Stream streamB = Stream.of(“李四”);
Stream newStream = Stream.concat(streamA, streamB);
// 合并后不能在操作之前的流
// 只支持将两个流合成一个
newStream.forEach(System.out::println);
综合案例
//第一个队伍
List streamA = one.stream().filter(s -> s.length() == 3).limit(3).forEach(System::println);
//3.第二个队伍只要姓张的成员姓名;
//4.第二个队伍筛选之后不要前2个人;
Stream streamB = two.stream().filter(s -> s.startsWith(“张”)).skip(2).forEach(System::println);
//5.将两个队伍合并为一个队伍;
Stream streamAB = Stream.concat(streamA, streamB);
//6.根据姓名创建Person对象;
//7.打印整个队伍的Person对象信息。
streamAB.map(Person::new).forEach(System::println);
收集Stream流中的结果
收集到集合中
Stream stream = Stream.of("aa", "bb", "cc");
List list = stream.collect(Collectors.toList());
System.out.println(list);
Set set = stream.collect(Collectors.toSet());
System.out.println(set);
// 收集到指定集合中ArrayList
ArrayList arrayList = stream.collect(Collectors.toCollection(ArrayList::new));
System.out.println(arrayList);
// 收集到指定集合中HashSet
HashSet hashSet = stream.collect(Collectors.toCollection(HashSet::new));
System.out.println(hashSet);
收集到数组中
Object[] objs = stream.toArray();
String[] strs = stream.toArray(String[]::new);
对流数据进行聚合计算
Stream studentStream = Stream.of(
new Student ( name: "赵丽颖", age: 58, socre: 95),
new Student ( name: "杨颖", age: 56, socre: 88)
new Student ( name: "迪丽热巴", age: 56, socre: 99),
new Student ( name: "柳岩", age: 52, socre: 77));
// 获取最大值
Optional max = studentStream.collect(Collectors.maxBy(s1, s2) -> s1.getSocre() - s2.getSocre);
System.out.println(max.get());
// 获取最小值
Optional min = studentStream.collect(Collectors.minBy(s1, s2) -> s1.getSocre() - s2.getSocre);
System.out.println(min.get());
// 求总和
Integer sum = studentStream.collect(Collectors.summingInt(s -> s.getAge()));
System.out.println(sum);
// 求平均值
Double avg = studentStream.collect(Collectors.averagingInt(s -> s.getSocre()));
System.out.println(avg);
Double avg = studentStream.collect(Collectors.averagingInt(Student::getSocre));
// 统计数量
Long count = studentStream.collect(Collectors.counting()));
System.out.println(count);
对流数据进行分组
// 对流数据进行分组
Stream studentStream = Stream.of(
new Student ( "赵丽颖", 52, 95),
new Student ( "杨颖", 56, 88),
new Student ( "迪丽热巴", 56, 55),
new Student ( "柳岩", 52, 33));
Map> map = studentStream.collect(Collectors.groupingBy((s) -> s.getAge()));
map.forEach((k, v) -> {
System.out.println(k + "::" + v);
});
Map> map = studentStream.collect(Collectors.groupingBy(Student::getAge));
// 将分数大于60的分一组,小于60的分一组
Map> map = studentStream.collect(Collectors.groupingBy((s) -> {
if (s.getScore() > 60) {
return "及格";
} else {
return "不及格";
}
}));
map.forEach((k, v) -> {
System.out.println(k + "::" + v);
});
对流数据进行多级分组
Map>> map = studentStream.collect(Collectors.groupingBy(Student::getAge, Collectors.groupingBy(s -> {
if (s.getScore() > 60) {
return "及格";
} else {
return "不及格";
}
})));
map.forEach((k, v) -> {
System.out.println(k);
v.forEach((k2, v2) -> {
System.out.println("\t" + k2 + " == " + v2);
});
});
对流数据进行分区
Map> map = studentStream.collect(Collectors.partitioningBy(s -> s.getScore() > 60));
map.forEach((k, v) -> {
System.out.println(k + "::" + v);
});
对流数据进行拼接
// 根据一个字符拼接
String names = studentStream.map(Student::getName).collect(Collectors.joining("_"));
System.out.println(names);
// 根据三个字符拼接
String names = studentStream.map(Student::getName).collect(Collectors.joining("_", "^_^", "v_v"));
System.out.println(names);
并行Stream流
获取并行Stream
流的两种方式
1 直接获取并行的Stream
流
list.parallelStream();
2 将串行流转成并行流
list.stream().parallel();
Stream.of(4, 5, 3, 9, 1, 2, 6).parallel().filter(
s -> {
System.out.println(Thread.currentThread() + "::" + s);
return s > 3;
}).count();
for、串行、并行效率对比
并行 > for > 串行
parallelStream线程安全问题
List list = new ArrayList<>();
IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
list.add(i);
});
System.out.println(list.size());
// 解决线程安全问题方案一:使用同步代码块
Object obj = new Object();
List list = new ArrayList<>();
IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
synchronized(obj) {
list.add(i);
}
});
System.out.println(list.size());
// 解决线程安全问题方案二:使用线程安全集合
//Vector vectorList = new Vector <>();
List list = new ArrayList<>();
List synchronizedList = Collections.synchronizedList(list);
IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
//vectorList.add(i);
synchronizedList.add(i);
});
System.out.println(list.size());
// 解决线程安全问题方案三:调用Stream流的collect和toArray方法
List list = IntStream.rangeClosed(1, 1000).parallel().boxed().collect(Collectors.toList());
System.out.println(list.size());