概念:
- 是JDK1.8的新语法 和IO流不是一个东西相当于流水线,很方便的对数据进行加工
- Stream流把真正的函数式编程风格引入到Java中,代码简洁
- Stream流不能直接修改数据源中的数据
- 不使用Stream流的优势是加工处理数据,每个需求都要循环一次,还要搞一个新集合来装数据, 麻烦
Stream流思想:
获取Stream流
创建一条流水线,并把数据放到流水线上准备进行操作
中间方法
流水线上的操作一次操作完毕之后,还可以继续进行其他操作
终结方法
一个Stream流只能有一个终结方法是流水线上的最后一个操作
Stream流的获取方法:
Collection体系集合
集合对象.stream();
Map体系集合
间接的生成流,通过keySet或者entrySet获取一个Set集合,再获取Stream流
集合对象.keySet.stream();
集合对象.entrySet.stream();
数组
通过Arrays中的静态方法stream生成流
Arrays.stream(数组名);
同种数据类型的多个数据
一个类型多个数据,没有放在集合和数组中,单独存在的
比如:int num = 1,2,3,4,5;
String num2 = “a”,“b”,“c”,“d”,“e”;
stream.of(数据1,数据2,数据3.....)
forEach :
forEach:用于迭代集合或流,可以对集合或流的元素进行特定操作的实用方法。
代码演示:
public class Demo02 {
public static void main(String[] args) {
//Collection体系的集合可以使用默认方法stream()生成流
List<String> list = new ArrayList<String>();
list.add("韩信");
list.forEach(s -> System.out.println(s));
//Map体系的集合间接的生成流,不能直接获取Stream
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("露娜", 22);
map.put("宫本", 32);
// 先获取所有的键,再把键放到Stream里
map.keySet().forEach(s -> System.out.println(s));
// 先获取键值对,再把键值对放在Stream里
map.entrySet().stream().forEach(s -> System.out.println(s));
//数组可以通过Arrays中的静态方法stream生成流
String[] strArray = {"hello", "world", "java"};
Arrays.stream(strArray).forEach(s -> System.out.println(s));
//同种数据类型的多个数据可以通过Stream接口的静态方法of(T... values)生成流
Stream.of("hello", "world", "java").forEach(s -> System.out.println(s));
Stream.of(10, 20, 30).forEach(s -> System.out.println(s));
}
}
Stream流的中间方法:
方法名 | 说明 |
---|---|
Stream filter(Predicate predicate) | 用于对流中的数据进行过滤 |
Stream limit(long maxSize) | 返回此流中的元素组成的流,截取前指定参数个数的数据 ,保留前面的 |
Stream skip(long n) | 跳过指定参数个数的数据,返回由该流的剩余元素组成的流 ,跳过前面的 |
static Stream concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
Stream distinct() | 去除流中重复的元素,依赖hashCode和equals方法 |
代码演示:
public class Demo03 {
public static void main(String[] args) {
// Stream filter(Predicate predicate) 用于对流中的数据进行过滤
List<String> list = new ArrayList<String>();
list.add("韩信");
list.add("李白");
list.add("猴子");
list.add("露娜");
list.add("宫本");
List<String> list2 = new ArrayList<String>();
list2.add("韩信2");
list2.add("李白2");
list2.add("猴子2");
list2.add("猴子2");
list2.add("露娜2");
list2.add("露娜2");
list2.add("宫本2");
// startsWith:方法用于检测字符串是否以指定的前缀开始。
// endswith:方法用于判断字符串是否以指定后缀结尾
list2.stream().filter(s -> s.startsWith("韩")).forEach(System.out::println);
// Stream limit(long maxSize) 截取前指定参数个数的数据
list.stream().limit(2).forEach(System.out::println);
// Stream skip(long n) 跳过前面的,保留后面的
list.stream().skip(2).forEach(System.out::println);
// static Stream concat(Stream a, Stream b) 合并a和b两个流为一个流
Stream.concat(list.stream(), list2.stream()).forEach(System.out::println);
// Stream distinct() 去除流中的重复元素,依赖于hashcode&equals
list2.stream().distinct().forEach(System.out::println);
}
}
获取Stream流的终结方法:
方法名 | 说明 |
---|---|
void forEach(Consumer action) | 对此流的每个元素执行操作 |
long count() | 返回此流中的元素数 |
代码演示:
public class Demo04 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("韩信");
// void forEach(Consumer action) 对此流的每个元素执行操作
list.forEach(System.out::println);
// long count() 返回此流中的元素数
System.out.println(list.stream().count());
}
}
Stream流的收集:
方法名 | 说明 |
---|---|
R collect(Collector collector) | 把结果收集到集合中 |
工具类Collectors提供了具体的收集方式
方法名 | 说明 |
---|---|
public static Collector toList() | 把元素收集到List集合中 |
public static Collector toSet() | 把元素收集到Set集合中 |
public static Collector toMap(Function keyMapper,Function valueMapper) | 把元素收集到Map集合中 |
代码演示:
public class Demo05 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(i);
}
/* filter:负责过滤数据
collect:负责收集数据
toList():把元素收集到List集合中,底层会创建一个List集合,并把所有的数据添加到集合
toSet():把元素收集到Set集合中,会去除重复
valueMapper:把元素收集到Map集合中
*/
List<Integer> tolist = list.stream().filter(num -> num % 2 == 0).collect(Collectors.toList());
System.out.println("tolist = " + tolist);
Set<Integer> toset = list.stream().filter(num -> num % 2 == 0).collect(Collectors.toSet());
System.out.println("toset = " + toset);
String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33", "柳岩,25"};
//得到字符串中年龄数据大于28的流
Stream<String> arrayStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);
//把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作键,年龄作值
Map<String, Integer> map = arrayStream.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
Set<String> keySet = map.keySet();
for (String key : keySet) {
Integer value = map.get(key);
System.out.println(key + "," + value);
}
}
}
- 我们发现Stream中的方法返回值分成两种,一种返回值还是Stream,另外一种返回值不是Stream
- 返回值类型还是Stream的方法,我们称为函数拼接方法
- 返回值类型不是Stream的方法,我们称为终结方法
Stream注意事项(重要):
1.Stream只能操作一次
2.Stream方法返回的是新的流
3.Stream不调用终结方法,中间的操作不会执行
使用Stream流操作数据2个步骤
1.得到Stream流
2.调用相应的方法
public class Demo12StreamForEach {
public static void main(String[] args) {
Stream<String> stream = Stream.of("张无忌", "张三丰", "周芷若");
stream.forEach(System.out::println);
}
}
count:统计个数
- 该方法返回一个long值代表元素个数
public class Demo09StreamCount {
public static void main(String[] args) {
Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");
Stream<String> result = original.filter(s -> s.startsWith("张"));
System.out.println(result.count()); // 2
}
}
filter:过滤
过滤,得到符合要求的数据
public class Demo07StreamFilter {
public static void main(String[] args) {
Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");
Stream<String> result = original.filter(s -> s.startsWith("张"));
}
}
limit:取用前几个
- 限制, 取前面n个数据
public class Demo10StreamLimit {
public static void main(String[] args) {
Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");
Stream<String> result = original.limit(2);
System.out.println(result.count()); // 2
}
}
skip:跳过前几个
- 跳过前面n条数据
public class Demo11StreamSkip {
public static void main(String[] args) {
Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");
Stream<String> result = original.skip(2);
System.out.println(result.count()); // 1
}
}
map:映射
- 映射,将一种类型的流转换成另一种类型的流
public class Demo08StreamMap {
public static void main(String[] args) {
Stream<String> original = Stream.of("10", "12", "18");
Stream<Integer> result = original.map(Integer::parseInt);
}
}
concat:组合
- 将两个流合并成一个流
public class Demo12StreamConcat {
public static void main(String[] args) {
Stream<String> streamA = Stream.of("张无忌");
Stream<String> streamB = Stream.of("张翠山");
Stream<String> result = Stream.concat(streamA, streamB);
}
}
4.收集Stream结果
我们使用Stream可以对数据进行处理.处理后怎么办?
收集到集合中
- 我们可以将流中的数据收集到集合或数组中
- public static Collector<T, ?, List> toList() :转换为 List 集合。
- public static Collector<T, ?, Set> toSet() :转换为 Set 集合。
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Demo15StreamCollect {
public static void main(String[] args) {
Stream<String> stream = Stream.of("10", "20", "30", "40", "50");
List<String> list = stream.collect(Collectors.toList());
Set<String> set = stream.collect(Collectors.toSet());
}
}
收集到数组中
Object[] toArray();
import java.util.stream.Stream;
public class Demo16StreamArray {
public static void main(String[] args) {
Stream<String> stream = Stream.of("10", "20", "30", "40", "50");
Object[] objArray = stream.toArray();
}
}