深入理解Java Stream流
原创
©著作权归作者所有:来自51CTO博客作者zhuhuix的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
背景
Java8新增了Stream流的API,允许用户使用lambda表达式,简单的操纵集合等数据结构。
Steram流的思想
- Stream不会存储数据,是有关算法和计算的,Stream就如同一个高级的流水线,单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。
- Stream可以并行化操作,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。Stream的并行操作依赖于Java7中引入的Fork/Join框架(JSR166y)来拆分任务和加速处理过程。
- Stream的数据源可以是集合、数组等。
使用Stream流的例子
当我们使用一个流的时候,通常包括三个基本步骤:
- 获取一个数据源 ;
- 数据转换 ;
- 执行操作获取想要的结果。
- 使用传统方式与Stream流API两种方式对比:过滤出集合中的偶数并输出。
/**
* 使用Stream流过滤集合中的数据
*
* @author zhuhuix
* @date 2020-07-26
*/
public class StreamFilterDemo {
public static void main(String[] args) {
// 创建一个集合,存放1到100的整数
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 100; i++) {
list.add(i);
}
// 使用传统方式过滤出偶数
for (Integer i : list) {
if (i % 2 == 0) {
System.out.println(i);
}
}
// 使用stream流方式过滤出偶数
Stream<Integer> stream = list.stream();
stream.filter(i -> i % 2 == 0).forEach(i -> System.out.println(i));
// 以下语句错误:Stream流只能使用一次
//stream.filter(i->i%2!=0).forEach(i -> System.out.println(i));
}
}
获取流的两种方式
1、根据Collection获取流
/**
* 通过Collection获取流
*
* @author zhuhuix
* @date 2020-07-26
*/
public class CollectionStream {
public static void main(String[] args) {
// 数组集合转换化Stream流
List<String> list = new ArrayList<>();
Stream<String> stringStream = list.stream();
// 将HashMap中的键值集合分别转化为Stream流
Map<String,String> map = new HashMap<>();
Set<String> keySet = map.keySet();
Stream<String> keyStream = keySet.stream();
Collection<String> values = map.values();
Stream<String> valueStream = values.stream();
}
}
2、根据Stream接口的静态方式of获取流
/**
* 通过Stream.of获取流
*
* @author zhuhuix
* @date 2020-07-26
*/
public class StreamOf {
public static void main(String[] args) {
//将数组通地Stream.of转换为Stream流
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7);
Integer[] array={1,2,3,4,5,6,7};
Stream<Integer> arrayStream = Stream.of(array);
}
}
Stream流的常用方法
1、forEach
- forEach用来遍历流中的数据,此方法是一个终结方法(调用此方法后不能继续调用Stream流的其他方法)
/**
* Stream流的forEach方法:void forEach(Consumer<? super T> action;
*
* @author zhuhuix
* @date 2020-07-26
*/
public class StreamForEach {
public static void main(String[] args) {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7);
integerStream.forEach(integer -> System.out.println(integer));
}
}
2、filter
/**
* Stream流的filter方法:Stream<T> filter(Predicate<? super T> predicate);
*
* @author zhuhuix
* @date 2020-07-26
*/
public class StreamFilter {
public static void main(String[] args) {
// 通过filter方法过滤出偶数
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7);
Stream<Integer> newIntegerStream = integerStream.filter(integer -> integer % 2 == 0);
newIntegerStream.forEach(integer -> System.out.println(integer));
}
}
3、map
- 通过map方法将流中的元素映射到另一个流中,比如元素类型的转换
/**
* Stream流的map方法:<R> Stream<R> map(Function<? super T, ? extends R> mapper);
*
* @author zhuhuix
* @date 2020-07-26
*/
public class StreamMap {
public static void main(String[] args) {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7);
// 将整型元素通过map方法转换成字符串类型
Stream<String> stringStream = integerStream.map(integer -> "字符:"+integer.toString());
stringStream.forEach(s -> System.out.println(s));
}
}
4、count
/**
* Stream流的count方法: long count();
*
* @author zhuhuix
* @date 2020-07-26
*/
public class StreamCount {
public static void main(String[] args) {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7);
long count = integerStream.count();
System.out.println(count);
}
}
5、limit
/**
* Stream流的limt方法: Stream<T> limit(long maxSize);
*
* @author zhuhuix
* @date 2020-07-26
*/
public class StreamLimit {
public static void main(String[] args) {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7);
// 取流中前4个元素
Stream<Integer> newIntegerStream = integerStream.limit(4);
newIntegerStream.forEach(integer -> System.out.println(integer));
}
}
6、skip
- 使用skip方法跳过前N个元素获取一个截取之后的新流
/**
* Stream流的skip方法: Stream<T> skip(long n);
*
* @author zhuhuix
* @date 2020-07-26
*/
public class SteamSkip {
public static void main(String[] args) {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7);
// 取流中前4个元素
Stream<Integer> newIntegerStream = integerStream.skip(4);
newIntegerStream.forEach(integer -> System.out.println(integer));
}
}
7、concat
/**
* Stream流的concat方法:<R> Stream<R> map(Function<? super T, ? extends R> mapper);
* public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
*
* @author zhuhuix
* @date 2020-07-26
*/
public class SteamConcat {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("a", "b", "c", "d");
Stream<String> stream2 = Stream.of("A", "B", "C", "D");
// 通过静态方法concat把两个流的元素合并形成新的流
Stream<String> stream = Stream.concat(stream1, stream2);
stream.forEach(s -> System.out.println(s));
}
}
Steram流的案例
/**
* Stream流的综合案例
*
* @author zhuhuix
* @date 2020-07-26
*/
public class StreamDemo {
public static void main(String[] args) {
// 创建两个班级的学生集合
List<Student> class1 = new ArrayList<>();
class1.add(new Student("jack", 91));
class1.add(new Student("mike", 90));
class1.add(new Student("jerry", 76));
class1.add(new Student("rose", 100));
List<Student> class2 = new ArrayList<>();
class2.add(new Student("kate", 99));
class2.add(new Student("tony", 86));
class2.add(new Student("sally", 94));
class2.add(new Student("billy", 83));
// 通过流的方式得出两个班级的超过90分的前三名学生
Stream<Student> stream1 = class1.stream().filter(student -> student.score > 90);
Stream<Student> stream2 = class2.stream().filter(student -> student.score > 90);
Stream.concat(stream1, stream2).sorted((s1,s2)->s1.compareTo(s2)).forEach(student -> System.out.println(student));
}
}
class Student implements Comparable {
String name;
Integer score;
Student(String name, Integer score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
@Override
public int compareTo(Object o) {
if (o instanceof Student){
return ((Student) o).score-this.score;
}
return -1;
}
}