加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

初识Java8中的Stream

发布时间:2020-05-28 04:17:58 所属栏目:Java 来源:互联网
导读:lambda表达式是stream的基础,初学者建议先学习lambda表达式,http://www.jb51.net/article/121129.htm

lambda表达式是stream的基础,初学者建议先学习lambda表达式,http://www.jb51.net/article/121129.htm

1.初识stream

先来一个总纲:

东西就是这么多啦,stream是java8中加入的一个非常实用的功能,最初看时以为是io中的流(其实一点关系都没有),让我们先来看一个小例子感受一下:

@Before
public void init() {
 random = new Random();
 stuList = new ArrayList<Student>() {
 {
 for (int i = 0; i < 100; i++) {
 add(new Student("student" + i,random.nextInt(50) + 50));
 }
 }
 };
}
public class Student {
 private String name;
 private Integer score;
 //-----getters and setters-----
}
//1列出班上超过85分的学生姓名,并按照分数降序输出用户名字
@Test
public void test1() {
 List<String> studentList = stuList.stream()
 .filter(x->x.getScore()>85)
 .sorted(Comparator.comparing(Student::getScore).reversed())
 .map(Student::getName)
 .collect(Collectors.toList());
 System.out.println(studentList);
}

列出班上分数超过85分的学生姓名,并按照分数降序输出用户名字,在java8之前我们需要三个步骤:

1)新建一个List<Student> newList,在for循环中遍历stuList,将分数超过85分的学生装入新的集合中

2)对于新的集合newList进行排序操作

3)遍历打印newList

这三个步骤在java8中只需要两条语句,如果紧紧需要打印,不需要保存新生产list的话实际上只需要一条,是不是非常方便。

2.stream的特性

我们首先列出stream的如下三点特性,在之后我们会对照着详细说明

1.stream不存储数据

2.stream不改变源数据

3.stream的延迟执行特性

通常我们在数组或集合的基础上创建stream,stream不会专门存储数据,对stream的操作也不会影响到创建它的数组和集合,对于stream的聚合、消费或收集操作只能进行一次,再次操作会报错,如下代码:

@Test
public void test1(){
 Stream<String> stream = Stream.generate(()->"user").limit(20);
 stream.forEach(System.out::println);
 stream.forEach(System.out::println);
}

程序在正常完成一次打印工作后报错。

stream的操作是延迟执行的,在列出班上超过85分的学生姓名例子中,在collect方法执行之前,filter、sorted、map方法还未执行,只有当collect方法执行时才会触发之前转换操作

看如下代码:

public boolean filter(Student s) {
 System.out.println("begin compare");
 return s.getScore() > 85;
}
 
@Test
public void test() {
 Stream<Student> stream = Stream.of(stuArr).filter(this::filter);
 System.out.println("split-------------------------------------");
 List<Student> studentList = stream.collect(toList());
}

我们将filter中的逻辑抽象成方法,在方法中加入打印逻辑,如果stream的转换操作是延迟执行的,那么split会先打印,否则后打印,代码运行结果为

初识Java8中的Stream

可见stream的操作是延迟执行的。

TIP:

当我们操作一个流的时候,并不会修改流底层的集合(即使集合是线程安全的),如果想要修改原有的集合,就无法定义流操作的输出。

由于stream的延迟执行特性,在聚合操作执行前修改数据源是允许的。

List<String> wordList;
 @Before
public void init() {
 wordList = new ArrayList<String>() {
 {
 add("a");
 add("b");
 add("c");
 add("d");
 add("e");
 add("f");
 add("g");
 }
 };
}
/**
 * 延迟执行特性,在聚合操作之前都可以添加相应元素
 */
@Test
public void test() {
 Stream<String> words = wordList.stream();
 wordList.add("END");
 long n = words.distinct().count();
 System.out.println(n);
}

最后打印的结果是8

如下代码是错误的

/**
 * 延迟执行特性,会产生干扰
 * nullPointException
 */
@Test
public void test2(){
 Stream<String> words1 = wordList.stream();
 words1.forEach(s -> {
 System.out.println("s->"+s);
 if (s.length() < 4) {
 System.out.println("select->"+s);
 wordList.remove(s);
 System.out.println(wordList);
 }
 });
}

结果报空指针异常

3.创建stream

1)通过数组创建

/**
 * 通过数组创建流
 */
@Test
public void testArrayStream(){
 //1.通过Arrays.stream
 //1.1基本类型
 int[] arr = new int[]{1,2,34,5};
 IntStream intStream = Arrays.stream(arr);
 //1.2引用类型
 Student[] studentArr = new Student[]{new Student("s1",29),new Student("s2",27)};
 Stream<Student> studentStream = Arrays.stream(studentArr);
 //2.通过Stream.of
 Stream<Integer> stream1 = Stream.of(1,5,65);
 //注意生成的是int[]的流
 Stream<int[]> stream2 = Stream.of(arr,arr);
 stream2.forEach(System.out::println);
}

2)通过集合创建流

/**
 * 通过集合创建流
 */
@Test
public void testCollectionStream(){
 List<String> strs = Arrays.asList("11212","dfd","2323","dfhgf");
 //创建普通流
 Stream<String> stream = strs.stream();
 //创建并行流
 Stream<String> stream1 = strs.parallelStream();
}

3)创建空的流

@Test
public void testEmptyStream(){
 //创建一个空的stream
 Stream<Integer> stream = Stream.empty();
}
4)创建无限流
@Test
public void testUnlimitStream(){
 //创建无限流,通过limit提取指定大小
 Stream.generate(()->"number"+new Random().nextInt()).limit(100).forEach(System.out::println);
 Stream.generate(()->new Student("name",10)).limit(20).forEach(System.out::println);
}

5)创建规律的无限流

/**
 * 产生规律的数据
 */
@Test
public void testUnlimitStream1(){
 Stream.iterate(0,x->x+1).limit(10).forEach(System.out::println);
 Stream.iterate(0,x->x).limit(10).forEach(System.out::println);
 //Stream.iterate(0,x->x).limit(10).forEach(System.out::println);与如下代码意思是一样的
 Stream.iterate(0,UnaryOperator.identity()).limit(10).forEach(System.out::println);
}

4.对stream的操作

1)最常使用

     map:转换流,将一种类型的流转换为另外一种流

/**
 * map把一种类型的流转换为另外一种类型的流
 * 将String数组中字母转换为大写
 */
@Test
public void testMap() {
 String[] arr = new String[]{"yes","YES","no","NO"};
 Arrays.stream(arr).map(x -> x.toLowerCase()).forEach(System.out::println);
}

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读