学习笔记(一):Java中Stream的基本用法和相关API详解

4 篇文章 0 订阅
订阅专栏

目录

引言

一、什么是Stream

二、Stream有什么用

三、Stream的分类

四、常用的Stream创建方法

 1. Stream.of()方法

2. Arrays.stream()

3. 集合对象中的stream()方法

五、Stream的常见操作

 API 实操记录(标红的是结束操作)

1. map()

2. forEach()

 3. peek()

4. collect()

3. count()

4.  fliter()

5. skip()

6. limit()

7. sorted()

8. distinct()

9. max(),min()

10. toArray()

11. mapToInt()、mapToDouble()、mapToLong()

12. boxed()

13. average()、sum()

结语


引言

在学习Kotlin语言的过程中,有被Kotlin中函数式编程的语法糖甜到,因此学习了Kotlin“本家”,Java相关的函数式编程知识。在学习Lambda表达式时接触到了Stream,通过阅读Java文档,博客等方式学习了相关API并且自己实操后,决定记录自己学习成果,也向不知道Stream的同学介绍一些Stream相关知识。

我也是一名学习者,在文章中如果有说明不正确或是不恰当的地方还请大佬指正,谢谢。

一、什么是Stream

1. Stream在Oracle Java 8 官方文档中的定义

Stream(中文翻译:流)是从Java 8 时起加入的Java,也正是从Java 8 起,Java中正式有了函数式编程、Lambda表达式等概念。

Stream的官方定义如下:

A sequence of elements supporting sequential and parallel aggregate operations. 

                                                                                                    —— Java 8 官方文档

个人渣翻:一个由一个或多个元素组成的、有顺序的、支持并行聚合的序列。

2. Stream的个人理解

上面文档中的定义翻译成人话就是,Stream不同于数组和List等,它是一个有顺序的长队,你可以对这个长队进行排序,或者是合并两个长队。你还可以把长队中的元素以一种特定的方法同一变为另一种元素。

二、Stream有什么用

对于我自己来说,我很多时候是把Stream作为一个工具来使用。

在不考虑时间成本的情况下,使用Stream的函数式编程相较于传统的过程式编程代码要更简洁,使用更加方便,但是相对的,代码可读性就会变得相对较差。

例如下面这段代码:

@Test
public void test() {
    int[] arr = {-5, -3, - 1, 0, 2, 4};
    for (int i = 0; i < arr.length; i++) {
        arr[i] *= arr[i];
    }
    Arrays.sort(arr);
    for (int i : arr) {
        System.out.println(i);
    }
}

这段代码的功能是将有序数组中元素做乘方运算并有序输出运算后的元素。

如果我们使用Stream编写同样功能的代码呢?

@Test
public void test() {
    int[] arr = {-5, -3, - 1, 0, 2, 4};
    Arrays.stream(arr).map(i -> i * i).sorted().forEach(System.out::println);
}

 我们可以先不管这段代码中使用的方法是什么意思,我们暂时只需要知道它可以实现和上一段代码一样的效果就可以了。可以看到,除去Junit注解,方法的定义和数组的定义,实现同样的功能,for循环(过程式编程)使用了7行,而使用Stream(函数式编程)只使用了1行。

这还只是比较简单的数组操作,如果换成更加复杂的业务、数组、或是集合,以for循环为代表的过程式编程就会显得更加臃肿、繁杂。使用Stream就可以使我们的代码简洁一些,也就不怎么会出现一个循环几十行的现象。

当然上面所说的一切都是建立在对时间要求不高的前提下,如果在算法比赛或是平时做算法题的过程中,偷懒使用Stream,就看你超不超时就完事儿了。

三、Stream的分类

在Java的官方文档中,我们可以知道,Stream是一个继承了BaseStream接口的泛型接口,其中泛型T是Stream中元素的类型。因此,不存在Stream<int>,Stream<double>这种Stream,但是可以有Stream<Integer>,Stream<Double>。因为Stream<T>流中只能存在对象,所以我喜欢将Stream<T>类型的流叫做对象流(非官方叫法,区别于IO操作中的输入输出对象流)。

public interface Stream<T> extends  BaseStream<T, Stream<T>>

                                                                                                    —— Java 8 官方文档

 那如果我不想把基本类型装箱成包装类,我就是要用int,怎么办呢?Java给提供我们了对应的“特殊”Stream。以int为例,Java提供了专属int的IntStream。从Java官方文档中不难看出,IntStream也继承自BaseStream接口,并且不是一个泛型接口。因此,我喜欢将这个流称为int流(非官方叫法)。当然也有对应的double流,long流,但是没有float流,byte流等其他基本类型的流。基本类型的流只有三种。

public interface IntStream extends  BaseStream< Integer, IntStream>

                                                                                                    —— Java 8 官方文档

 注意:Stream<T>和IntStream(以IntStream为例)虽然可以相互转换,但是IntStream不是Stream<T>,他们都继承自BaseStream,是兄弟关系,不是父子。(以下使用的Stream如不进行指出,则代指两者)

四、常用的Stream创建方法

常用的(我会用的)创建Stream的方式主要有三种,如表1:

表1 Stream的创建方式
创建方式可以创建的Stream类型
Stream.of()Stream<T>
Arrays.streamIntStream,DoubleStream,LongStream,Stream<T>
集合对象中的stream()方法Stream<T>

 1. Stream.of()方法

 我们先看官方文档:

                                                                                                     —— Java 8 官方文档

 在文档中我们可以看出of()是静态方法,可以直接通过Stream<T>类名调用,并且of()的形参可以输入一个或者多个,然后返回一个元素类型为形参类型的Stream<T>。

代码示例如下:

Stream<Integer> stream = Stream.of(1, 2, 3, 4);
    
Stream<String> stream = Stream.of("aaa", "bbb");

注意:不能使用如下代码创建Stream(除非你想要Stream<int[]>类型的流)。

int[] arr = {-5, -3, - 1, 0, 2, 4};
Stream.of(arr);

使用这种方法创建出来的Stream类型是Stream<int[]>,不是Stream<Integer>。

2. Arrays.stream()

这种方式使用的是Java自带的数组工具类Arrays中的静态方法stream()进行创建。

                                                                                                      —— Java 8 官方文档

 Arrays类中对stream()方法进行了多次覆写,接收不同类型的(包括有对应基本类型流的三种基本类型)数组,返回对应的Stream。输入对象数组返回对象流,输入基本类型数组返回基本类型流。

代码示例:

Stream<String> stringStream = Arrays.stream(new String[]{"aa", "bb", "cc"});
IntStream intStream = Arrays.stream(new int[]{1, 2, 3});
//报错
Arrays.stream(new char[]{'a', 'b', 'c'});

3. 集合对象中的stream()方法

这种方法使用的是一些集合对象中自带的stream()方法将集合对象转换为Stream<T>类型的流。因为大多数集合也都是泛型,所以,使用这种方法只能创建Stream<T>类型的流。

代码示例:

//常见的集合转Stream
List<Integer> list = new ArrayList<>();
Stream<Integer> listStream = list.stream();
Set<Integer> set = new HashSet<>();
Stream<Integer> setStream = set.stream();
Map<String, Integer> map = new HashMap<>();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();

注意:Map类型的集合不能直接转换为Stream<T>,必须先将Map对象转换为EntrySet才能使用 stream()方法进行转换。

五、Stream的常见操作

 创建了流对象后,我们就得学会使用它。

 !!!在Stream的使用中会大量地使用到Lambda表达式。不知道Lambda表达式的同学可以先学习Lambda表达式。

流的操作非常多,其中比较常用(会用)的操作如下(随缘排序):

表2 常用的Stream通用操作
Stream操作释义
map()将流中每一个元素通过指定方式应成为另一个元素
forEach()遍历流(结束操作)
peek()遍历流
collect()将流转换为集合对象(结束操作)
count()返回流中元素的个数,返回值为long(结束操作)
fliter()过滤流中不符合条件的元素
skip()跳过流中的前几个元素
limit()限制流的长度,超出长度时去掉超出的元素
sorted()对流中的元素进行排序,可自定义排序规则
distinct()去除流中相同的元素
max()、min()求出根据条件得到流中最大(最小)元素,返回一个Optional对象(结束操作)
toArray()将流对象转换为数组(结束操作)
findFirst()获取流中的第一个元素,返回一个Optional对象
findAny()随机获取流中的一个元素,返回一个Optional对象
mapToInt()、mapToDouble()、mapToLong()将Stream<T>按照映射方法转换为对应的基本类型的流
表3 基本类型流中常用操作
基本类型流操作释义
boxed()将基本类型的流包装为Stream<T>类型流
average()求出流中所有元素的平均数,返回一个DoubleOptional对象(结束操作)
sum()求出流中所有元素的和,返回值类型由流的类型决定(结束操作)

在这些操作中,标记“结束操作”的方法不会返回Stream对象,也就是说,当前流使用了该方法后就无法通过链式调用的方法对当前流进行操作。并且,调用了结束操作的流无法被再次使用,即流在调用了结束操作后会被关闭。强制执行会报以下错误:

//错误示范
public void test() {
    List<Integer> list = new ArrayList<>(){{
        add(1);
        add(2);
    }};
    Stream<Integer> stream = list.stream();
    stream.max(Integer::compareTo);
    List<Integer> collect = stream.collect(Collectors.toList());
}

也就是说,结束操作必须在最后调用

 API 实操记录(标红的是结束操作

1. map()

在前面表2中,我说是“随缘排序”,但也是夹带了一点私货。我觉得map()可以说是Stream的精髓,会用了map(),其他Stream的方法怎么用、是干什么的基本都写在方法名上了。正是因为map()之于Stream,正如锅巴之于煲仔饭,土豆之于英国,是精髓之所在,所以在表中将其放在了第一位。

Java 8 官方文档中对Stream中map()的描述如下:

<R>  Stream<R> map( Function<? super  T,? extends R> mapper)

Returns a stream consisting of the results of applying the given function to the elements of this stream.

                                                                                                       —— Java 8 官方文档

本人渣翻:返回一个包含了将所有元素应用于给定函数所返回的结果的流。

看不懂也没关系,结合实操,很快就能明白。

观察如下代码:

public void test() {
    List<Integer> list = new ArrayList<>(){{
        add(1);
        add(2);
        add(3);
    }};
    Stream<Integer> integerStream = list.stream();
    Stream<String> stringStream = integerStream.map(i -> String.valueOf(i));
}

我们创建了一个{1, 2, 3}的List集合,通过集合自身的stream()方法获得了一个Stream<Integer>类型的integerStream,然后integerStream调用了map()方法,然后就得到了一个Stream<String>类型的stringStream,发生了什么?重点就在map中的Lambda表达式。在这个表达式“i -> String.valueOf(i)”中,"i"代表的就是integerStream中的一个元素,而“String.valueOf()”就是map()执行映射的方法。在调用了map()方法后,流对象会从第一个元素执行执行映射方法,并且把映射方法的返回值作为流中新的元素。

再讲通俗一点就是,“i”代表流中的一个元素,“->”可以理解为“变成”,这个Lambda表达式的意思就是,流中的元素i变成了“->”后面这个方法的返回值。而map()会对流中的每一个元素执行这种操作。

注意:因为map()会将映射方法的返回值作为流中的新元素,因此,被引用的映射方法必须有返回值。

情景实例(因为懒,Student采用内部类的形式,下面可能会多次用到):

你的手中现在有四个学生的名字,使用这四个名字构建一个Student对象流,分数采用随机数,然后再将Student对象流映射为只包含成绩的Double对象流。

class Tests {

    private static final class Student {

        private String name;
        private double score;

        Student(String name, double score) {
            this.name = name;
            this.score = score;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public double getScore() {
            return score;
        }

        public void setScore(double score) {
            this.score = score;
        }
    }

    @Test
    public void test() {
        Stream<String> stringStream = Stream.of("小明", "小红", "小亮", "小刚");
        Stream<Student> studentStream = stringStream.map(name -> new Student(name, Math.random() * 100 + 1));
        Stream<Double> doubleStream = studentStream.map(student -> student.getScore());
    }

}

我们可以采用链式调用的方式将代码精简(以下都将采用链式调用):

Stream<Double> doubleStream = Stream.of("小明", "小红", "小亮", "小刚")
                                .map(name -> new Student(name, Math.random() * 100 + 1))
                                .map(student -> student.getScore());

2. forEach()

 接收一个Consumer类型的参数,对流中的每一个元素执行对应的操作。

情景实操:

控制台输出四个学生对象组成的流中的每一个元素(Student已有toString()方法)。

//Student类同上
@Test
public void test() {
    Stream.of("小明", "小红", "小亮", "小刚")
            .map(name -> new Student(name, (int) ((Math.random() * 100 + 1) * 100) / 100.0))
            .forEach(student -> System.out.println(student));
}

我们可以使用Lambda的方法引用进一步精简代码(以下都将采用Lambda方法引用):

@Test
public void test() {
        Stream.of("小明", "小红", "小亮", "小刚")
            .map(name -> new Student(name, (int) ((Math.random() * 100 + 1) * 100) / 100.0))
            .forEach(System.out::println);
}

运行结果:

 3. peek()

效果和forEach()一样,同样是接收一个Consumer类型的参数,都是遍历流。区别就是forEach()会关闭流,是结束操作,而peek()不会,调用peek()后,任然可以调用其他操作。

主要使用场景:debug,修改流中的某一个或某一些元素等。

4. collect()

调用该方法会对流进行包装,返回结果为包装后的集合(List、Map、Set等)。

情景实操:

将映射完成的学生对象流封装为List、Map(其中Map以name作key,score作value)。

@Test
public void test() {
    List<Student> list = Stream.of("小明", "小红", "小亮", "小刚")
            .map(name -> new Student(name, (int) ((Math.random() * 100 + 1) * 100) / 100.0))
            .collect(Collectors.toList());
}
@Test
public void test() {
    Map<String, Double> map = Stream.of("小明", "小红", "小亮", "小刚")
            .map(name -> new Student(name, (int) ((Math.random() * 100 + 1) * 100) / 100.0))
            .collect(Collectors.toMap(Student::getName, Student::getScore));
}

3. count()

真正的人如其名,不做作,无参方法,返回一个long型的值,该值为流的长度或者说是流中元素的个数。

4.  fliter()

该方法接收一个Predicate类型的参数,根据条件过滤掉不符合条件的元素。

情景实操:

在学生对象流中过滤掉分数低于80分的学生并输出。

@Test
public void test() {
    Stream.of("小明", "小红", "小亮", "小刚")
            .map(name -> new Student(name, (int) ((Math.random() * 100 + 1) * 100) / 100.0))
            .peek(s -> System.out.println("过滤之前 ====>" + s))
            .filter(student -> student.getScore() > 80)
            .forEach(s -> System.out.println("过滤之后 ====>" + s));
    }

运行结果:

 

从这里我们也可以看出peek()和forEach()的区别。

5. skip()

接收一个long类型的参数n,意为跳过或者说去掉前n个流中的元素。

6. limit()

接收一个long类型的参数n,意为去掉流中第n个元素之后的元素。

7. sorted()

Steam<T>中覆写了两个sorted()方法,一个是无参的,一个接收一个Comparator比较器类型的参数。我们先看无参的官方文档:

Returns a stream consisting of the elements of this stream, sorted according to natural order. If the elements of this stream are not Comparable, a java.lang.ClassCastException may be thrown when the terminal operation is executed.

For ordered streams, the sort is stable. For unordered streams, no stability guarantees are made.

                                                                                                       —— Java 8 官方文档

 本人渣翻:返回一个包含了所有这个流中的元素,并且这些元素经过自然顺序排序过。如果这些元素不是可以比较的(即没有实现Comparable接口),执行终端操作时可能会抛出一个java.lang.ClassCastException。对于有序流,排序是稳定的;对于无序流,不保证排序是稳定的。

了解了无参的sorted(),我们可以看一下有参的sorted()。它接收的比较器参数其实就是为了给没有实现Comparable接口的这些无法比较的元素一个比较规则,或者覆盖可比较元素的已有比较规则。

代码示例:

使用无参sorted()排序数字:

@Test
public void test() {
    Stream.of(3, 1, 2, 4, 0)
            .sorted()
            .forEach(System.out::println);
}

使用无参sorted排序字符串:

@Test
public void test() {
    Stream.of("kaoji", "baozaifan", "chongqinghuoguo", "hongzuilvyinggeer")
            .sorted()
            .forEach(System.out::println);
}

按照字典序排序,自动调用了String中的compareTo()方法;

 使用有参sorted(),根据字符串长度排序:

@Test
public void test() {
    Stream.of("kaoji", "baozaifan", "chongqinghuoguo", "hongzuilvyinggeer")
            .sorted((str1, str2) -> str1.length() - str2.length())
            .forEach(System.out::println);
}

8. distinct()

该方法主要用于去重。

如果类中元素的类没有重写equals()方法和hashCode()方法,该方法会比较两个元素的地址,如果地址一样,判断为重复;如果地址不一样,即使对象的内容一样,也判断为不重复。

如果重写了equals()方法和hashCode()方法,则该方法会自动调用equals方法进行判断是否重复。

9. max(),min()

注意两个方法均为有参方法,它们没有无参的覆写方法,接收参数为一个比较器。方法根据提供的比较器求出流中的最大值。

如果你的流中元素是可比较的(即实现了Comparable接口的),并且你没有特殊的比较要求,以Integer类举例,你可以这样使用:

Integer integer = Stream.of(1, 2, 3, 4, 5)
            .max(Integer::compareTo).get();

 因为max()方法返回值是一个Optional对象,Optional是一个泛型接口,它是对对象的进一步封装,为了防止在一切地方抛出空指针异常,因此我们需要使用Optional接口中的get()方法取出Optional封装的对象。

10. toArray()

这也是一个比较常用的方法,方法的作用显而易见,就是将流转换为一个数组。

特别注意!!!这个方法有在接口内进行了一次覆写,因此有两个toArray()方法,一个无参,一个接收IntFunction类型的参数。

先说无参方法,通过查看Java 8的官方文档我们可以知道,无参的toArray()方法返回的是一个Object[]类型的数组。因此,不管流中的元素是什么类型,最后你得到的都是一个Object[]类型的数组,切记,切记,切记!但是,如果当前流是基本类型流,则无参toArray()方法会直接返回对应类型的数组。例如IntStream的流对象调用无参toArray()方法会返回一个int数组。

再看有参的toArray()方法,我们不用知道IntFunction这个接口是干什么,我们只用知道它能够帮我们把流转换成流中元素对应类型的数组就可以了。因此我们只需要告诉方法我们需要什么类型的数组即可。具体操作如下。切记是“Integer[]::new”,不是“Integer::new”。

Integer[] array = Stream.of(1, 2, 3, 4, 5).toArray(Integer[]::new);

11. mapToInt()、mapToDouble()、mapToLong()

这三个方法的作用基本都一样,因此这里只对mapToInt()进行说明。

方法接收一个ToIntFunction类型的参数,也就是说这个方法需要我们提供一个映射方法,这个映射方法可以将流中的元素映射为int。该返回一个IntStream。

因此,mapToInt()中的映射方法的返回值必须是int。使用如下:

IntStream stream = Stream.of(1, 2, 3, 4, 5).mapToInt(Integer::intValue);

12. boxed()

这是基本类型流(IntStream等)中特有的方法,即对基本类型流中的元素进行装箱,返回对应的包装类流。

这是一个无参方法。具体效果如下:

IntStream stream = Stream.of(1, 2, 3, 4, 5).mapToInt(Integer::intValue);
Stream<Integer> boxedStream = stream.boxed();

13. average()、sum()

这两使用方法都差不多,就放一起讲了。它们都是基本类型流特意有的方法,average()方法是求出流中所有元素的平均数,sum()方法是求出流中所有元素的总和。

average()方法的返回值固定是double类型,sum()的返回值是由基本类型流的类型决定的,IntStream返回int,DoubleStream返回double,LongStream返回long。

两个方法都是无参方法,可以直接调用。

当你Stream熟练后,你就会发现大多数情况下把对象流(Stream<T>)转换为基本类型流基本都是为了使用这俩儿。

结语

讲到这也差不多了,Stream真的是Java中一个非常好用的工具,在不用考虑时间成本的情况下可以让我们少码很多的代码,让我们的代码相对更加简洁。我也不是说函数式编程就怎么怎么好,你用过程式编程就怎么怎么不好。当然不是,使用什么编程风格是由自己决定的,如果你实在是搞不明白Lambda表达式,使用过程式编程也完全Ok呀。有句老话说得好:“管他什么代码,能跑的就是好代码!!!”

我不知道是不是因为Lambda表达式的原因,很多人都不太使用Stream,甚至许多Java使用者都不知道这个东西。我问了我的两名使用Java开发过应用程序的室友,“在开发中你是用过Stream吗?”,一室友表示“完全没有使用过”,另外一室友表示“平常不用,数组偶尔使用”。当然也不排除有各种Python、Kotlin、C#的大佬看不上Java的函数式编程而不想使用,不得不承认,Java的函数式编程相较于其他语言还是没那么香,大佬随意就好。

我也是想通过这篇文章让更多人了解Stream,知道Stream相关的API以及Stream有什么用,同时也为自己做一个笔记,加深自己对这一块知识的了解。

“学而不思则罔,思而不学则殆”,讲了这么多,重要的还是在实际开发过程中多多使用才能真正的掌握。

文章中如果有不正确或是不准确的地方,欢迎指正,谢谢。

[Java]“语法糖”系列(三)之集合流操作(Stream)[笔记]
身披白袍的博客
11-25 2157
这里的这个流和IO流不一样,是JDK8对Collection对象功能的加强。
Java学习笔记
VanMonday的博客
05-12 1125
兰智数加Java学习笔记
Arrays.stream
m0_61594817的博客
01-17 8063
总之,Arrays.stream() 函数可以将数组转换为流,使用流API可以更简洁的处理数组的数据,在大量数据的情况下可以提高性能。流是一种新的数据处理模型,可以对数据进行并行处理,提高程序的性能。使用 Arrays.stream() 方法可以将数组转换为流,然后就可以对数组的元素进行各种操作,例如过滤,映射,排序等。举个例子,假设有一个整型数组,需要将所有大于10的数加上1,使用传统方法需要循环遍历数组并进行判断,而使用流API可以这么写。
【流式编程】Stream.of()用法解析及使用示例
最新发布
qq_39666711的博客
08-26 604
Stream.of() 方法可以接受任意数量的参数,这些参数将作为流的元素。你可以传递任意类型的参数给这个方法,只要所有参数的类型相同,或者它们之间存在适当的自动装箱/拆箱关系。在这个示例,我们首先使用 Stream.of() 创建一个整数流,然后使用 filter() 方法过滤出偶数,最后使用 sum() 方法计算这些偶数的和。这个示例创建了一个包含四个字符串的流,并使用 forEach 方法打印出流的每个元素。的一个静态方法,用于从给定的元素创建一个顺序流(Sequential。
java8-stream
qq_42772400的博客
09-15 962
Java 8 Streams API 详解 为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 StreamJava 8 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate ope
java8 arrays.stream_Java8 获取一个Stream,选择 Arrays.stream() 还是 Stream.of() ?
weixin_33232907的博客
02-27 1195
在网上搜了一下。对于对象数组/列表,两个方法都调用了 Arrays.stream :Integer[] array = { 1, 2, 3, 4, 5 };Stream.of(array)// return Stream.forEach(System.out::println); // prints 1, 2, 3, ...Integer[] array = { 1, 2, 3, 4, 5 };...
JAVA流编程】Arrays.stream(T[] array) 用法
qq_39666711的博客
08-26 207
使用流,你可以进行复杂的查询/过滤操作、映射转换、归约等操作,而这一切都可以以声明式的方式完成,代码更加简洁、易于理解。假设你有一个整型数组,你想要找出其所有的偶数,并计算它们的和。Arrays.stream() 函数可以将数组转换为流,使用流API可以更简洁的处理数组的数据,在大量数据的情况下可以提高性能。使用 Arrays.stream() 方法可以将数组转换为流,然后就可以对数组的元素进行各种操作,例如过滤,映射,排序等。引入的一个非常有用的方法,它允许你以流(Stream)的形式处理数组。
Java程序设计学习笔记:第1-29章精华汇总
资源摘要信息:"Java语言程序...总结来说,本学习笔记是针对Java语言程序设计的全面入门和提升材料,适用于不同层次的Java学习者,特别是对于想要打好基础或系统提升Java技能的学习者来说,是一份不可多得的学习资源。
Java8 Stream详解:Lambda与Fork-Join应用
Java8之Stream》是一本深入讲解这一特性的教程,作者汪文君分享了他的学习笔记,旨在帮助读者理解和掌握Stream用法。书内容包括以下几个部分: 1. **Stream简介**:首先,作者介绍了Stream基本概念,强调它...
Java8之Stream学习:删除重复数据,保留第一条
"Java8之Stream学习笔记,包括Stream简单介绍、HelloWorld示例、Fork-Join机制、Stream使用详解等内容,旨在帮助读者理解Java8的新特性" 本文主要介绍了Java8的一个重要特性——Stream API,它带来了全新的数据...
黑马程序员_java8新特性详解笔记和源码
07-27
Java 8是Java语言发展的一个重要里程碑,引入了许多创新性的特性和改进,...黑马程序员的Java8新特性详解笔记和源码提供了深入学习这些概念的资源,结合实际的代码示例,将有助于你更好地理解和掌握Java 8的核心特性。
java 基本语法(十八)Lambda (五)Stream API
创业项目
07-11 324
1.Stream API的理解: 1.1 Stream关注的是对数据的运算,与CPU打交道 集合关注的是数据的存储,与内存打交道 1.2 java8提供了一套api,使用这套api可以对内存的数据进行过滤、排序、映射、归约等操作。类似于sql对数据库表的相关操作。 2.注意点: * ①Stream 自己不会存储元素。 * ②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。 * ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。 3.Stream
深入学习java源码之Arrays.asList()与Arrays.stream()
热门推荐
悦分享
01-06 1万+
深入学习java源码之Arrays.asList()与Arrays.stream() RandomAccess标记接口 标记接口,Marker interface,它们是一类没有定义任何接口方法的接口,表现为一个空接口  没有接口方法意味着实现该接口的类无需实现任何接口方法,仅仅作为一种标记,以供其他方法判断  作用就是当某个类实现这个接口后即拥有了这个接口的功能,Java 虚拟机在运行时会识...
Java stream
weixin_38400347的博客
03-02 1446
流处理 需求:从用户集合获取id为基数的用户名称,得到名称集合 public static void main(String[] args) { List<User> userList = new ArrayList<>(); for (int i = 0; i < 10; i++) { User user = new User(i, "name" + i); userList.add(u
java求整型数组的平均值(先使用Arrays.stream,然后求平均)
听海边涛声
05-01 701
用了另外一种方法求JAVA整型数组的平均值。首先用Arrays.stream进行转换,然后再求平均
JAVA——Stream
2303_76897008的博客
02-04 1654
有两个集合,分别存储六个演员年龄和姓名,现需男演员只要名字为3个字的前两个人,女演员只要姓杨的并且不要第一个,再将得到的两个集合合并为一个集合并且封装成以一个Actor对象,最后将数据存到集合list
java Steam流的用法
zouyang920的博客
05-13 329
java Steam流的用法1 java Steam流的用法2 项目的流用法不太懂,沾出来大家一路分享,有清楚地可以评论留言。
Java集合、数组对Stream的介绍和用法
m0_51044974的博客
02-16 2377
javaStream对集合和数组的高效操作
JavaStream使用
zhangying_496的博客
08-10 1217
javaStream 使用
写文章

热门文章

  • Scala下载及安装(Windows)以及Idea中Scala项目的创建 4617
  • 学习笔记(一):Java中Stream的基本用法和相关API详解 2569
  • 踩坑笔记(一):MyBatis查询不到驼峰命名的变量 1855
  • Scala模式匹配(Pattern Matching)——match - case 1345
  • 学习笔记(二):Java中的equals()和hashCode() 552

分类专栏

  • 我的Scala学习之路 2篇
  • 设计模式 1篇
  • 学习笔记 4篇
  • 踩坑笔记 1篇

最新评论

  • 踩坑笔记(一):MyBatis查询不到驼峰命名的变量

    weixin_ab: mybatis-plus: configuration: map-underscore-to-camel-case: true

  • 学习笔记(一):Java中Stream的基本用法和相关API详解

    ForMoree: wow~

  • 学习笔记(一):Java中Stream的基本用法和相关API详解

    CSDN-Ada助手: Java 技能树或许可以帮到你:https://edu.csdn.net/skill/java?utm_source=AI_act_java

  • 学习笔记(一):Java中Stream的基本用法和相关API详解

    鸢ci音陌: 大佬讲得真的太详细了,很难听不懂表情包

大家在看

  • Vulhub Rickdiculously Easy 靶机详解
  • 基于深度学习的机器人智能控制算法 仿真环境1 323
  • 浙大恩特CRM Quotegask_editAction SQL注入漏洞复现
  • SpringBoot获取bean的几种方式 1241
  • 前端开发设计模式——工厂模式 616

最新文章

  • Scala模式匹配(Pattern Matching)——match - case
  • (一)二十三种设计模式之单例模式
  • Scala下载及安装(Windows)以及Idea中Scala项目的创建
2022年7篇

目录

目录

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家普洱玻璃钢雕塑设计多少钱商场dp景点美陈装饰男装观山湖区玻璃钢雕塑厂家开封肖像玻璃钢卡通雕塑定制湖北定做玻璃钢雕塑生产玻璃钢雕塑厂家哪家好三八女王节商场美陈布置图片南通玻璃钢雕塑工厂合肥玻璃钢雕塑欢迎来电商场橱窗美陈活动方案玻璃钢雕塑花车玻璃钢动物雕塑值得信赖江苏人物玻璃钢雕塑工业吉林玻璃钢雕塑模型潮州玻璃钢花盆花器阳江定制玻璃钢动物雕塑山东玻璃钢卡通雕塑定制丽江市玻璃钢雕塑设计报价杭州玻璃钢传统人物雕塑池州多彩玻璃钢雕塑销售电话玻璃钢雕塑安装视频教程玻璃钢陶瓷雕塑介绍湖北玻璃钢大猩猩雕塑北京玻璃钢雕塑造型玻璃钢雕塑人物品牌河北商场美陈哪里有漯河玻璃钢雕塑多少钱湖南仿铜玻璃钢雕塑厂家通辽广场玻璃钢雕塑生产厂家发光小品玻璃钢雕塑现货销售香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化