【Java # lambda表达式】

1. lambda表达式

java8的新特性,lambda可以作为方法的参数,lambda也可以作为一个返回。

2.可以做什么

简化接口实现
之前我们,可以使用1.使用具名接口实现类;2.匿名实现类
使用lambda,这两种方式都可以用了。

3.使用lambda的要求:

函数式接口(说人话就是接口只有一个抽象方法)

4.满足了函数式接口后,看一下lambda语法

(参数1,参数2)-> {方法体};
说明: 当多个参数的时候,需要用小括号包起来,当方法体是多行时,必须用花括号包起来。
 参数1 -> {方法体};
 说明: 当只有一个参数的时候,可以省略小括号
 参数1 -> 参数1 + 12;
 说明: 当方法体之后一句执行语句的时候,可以省略花括号;并且返回值时,可以省略return;
 () -> a+b;
 说明:当参数为空是,必须有小括号。

5. 方法引用

5.1 静态方法引用

//静态方法引用
public class Test05 {
    public static void main(String[] args) {
        Test1 test1 = Calculator::calculate; //静态方法引用
        System.out.println(test1.test(4,5));
    }
}

class Calculator{
    public static int calculate(int a,int b ){
        // 稍微复杂的逻辑:计算a和b的差值的绝对值
        if (a > b) {
            return a - b;
        }
        return b - a;
    }
}

5.2 非静态方法引用

// 非静态方法引用
public class Test06 {
    public static void main(String[] args) {
        //对非静态方法的引用,需要使用对象来完成
        Test2 test2 = new Calculator()::calculate;
        System.out.println(test2.calculate(2, 3));
    }
    private static class Calculator{
        public int calculate(int a, int b) {
            return a > b ? a - b : b - a;
         }
    }
}

5.3 构造方法的引用

// 如果某⼀个函数式接口中定义的方法,仅仅是为了得到⼀个类的对象。此时我们就可以使用构造方法的引
// 用,简化这个方法的实现。
// 语法:类名::new

public class Test {
    private static class Dog{
        String name;
        int age;
        //无参构造
        public Dog(){
            System.out.println("一个Dog对象通过无参构造被实例化了");
        }
        //有参构造
        public Dog(String name,int age){
            System.out.println("一个Dog对象通过有参构造被实例化了");
            this.name = name;
            this.age = age;
        }
    }
    //定义一个函数式接口,用以获取无参的对象
    @FunctionalInterface
    private interface GetDog{
        //若此方法仅仅是为了获得一个Dog对象,而且通过无参构造去获取一个Dog对象作为返回值
        Dog test();
    }

    //定义一个函数式接口,用以获取有参的对象
    @FunctionalInterface
    private interface GetDogWithParameter{
        //若此方法仅仅是为了获得一个Dog对象,而且通过有参构造去获取一个Dog对象作为返回值
        Dog test(String name,int age);
    }

    // 测试
    public static void main(String[] args) {
        //lambda表达式实现接口
        GetDog lm = Dog::new; //引用到Dog类中的无参构造方法,获取到一个Dog对象
        Dog dog = lm.test();
        System.out.println("修狗的名字:"+dog.name+" 修狗的年龄:"+dog.age); 
        //修狗的名字:null 修狗的年龄:0
        GetDogWithParameter lm2 = Dog::new;//引用到Dog类中的有参构造,来获取一个Dog对象
        Dog dog1 = lm2.test("萨摩耶",2);
        System.out.println("修狗的名字:"+dog1.name+" 修狗的年龄:"+dog1.age);
        //修狗的名字:萨摩耶 修狗的年龄:2
    }
}

6. Lambda与泛型结合之终极使用方案:

/**
 * 说明: 我猜大概二毛看不懂了吧!那就对此进行个说明吧
 *  首先定义了一个泛型方法processElements()
 *  泛型的方法参数都是接口:
 *  ① Iterable: 可迭代的对象接口
 *  ② Predicate: 判断条件,返回布尔类型的函数式接口
 *  ③ Function: 传入一个参数,返回一个结果的函数式接口
 *  ④ Consumer:消费一个参数,返回值为void的函数式接口
 * 程序的作用:给processElements方法传入一个可迭代的对象,一个用来判断的条件函数,一个函数式接口
 * 				实现,一个消费者函数式接口实现,最终通过遍历,使用传入的条件函数用来做判断,使用
 * 				apply,消费一个参数,返回一个data;最后使用consumer直接消费掉!
 */
public static <X, Y> void processElements(
    Iterable<X> source,
    Predicate<X> tester,
    Function <X, Y> mapper,
    Consumer<Y> block) {
    for (X p : source) {
        if (tester.test(p)) {
            Y data = mapper.apply(p);
            block.accept(data);
        }
    }
}

7. jdk8里面规定的一些函数式接口:

  • Consumer 消费型接口 ,返回void
  • Supplier: 供给型接口,返回T类型
  • Function<T,R> 函数型接口,返回R类型
  • Predicate 断言型接口 ,返回boolean

8. jdk8对容器的操作 — 流stream:

说明:流是对容器操作的简洁方法,并且使用到了Lambda表达式,它能充分利用多核优势,以及配合Lambda表达式、链式结构对集合进行许多好用的操作。

8.1 创建流stream

8.1.1 从Collection和数组获得

// 1. 通过Collection系列提供stream()串行流和parallelStram()并行流
Collection.stream();		 // 转换为串行流
Collection.parallelStream(); //转换为并行流
// 2. 通过Arrays中的静态方法stream()返回数据流
Arrays.stream(T array);
/* 注意:对于基本数据类型,目前提供了对应的包装类型流: IntStream、LongStream、DoubleStream。
当然也可以使用Stream<Integer>、Stream<Long>、Stream<Double>,但是会很耗时,所以特别为这三种提供
了数值型对应的Stream。
*/

8.1.2 Stream接口的静态工厂

// 1. of()方法:其生成的stream是有限长度的,stream的长度为其内的元素个数。
Stream.of(T ...values) //返回含有多个T元素的
Stream.of(T t) //返回含有一个T元素的Stream
// 示例:
Stream<Integer> integerStream = Stream.of(1, 2, 3);
Stream<String> stringStream = Stream.of("A");

// 2.generate()方法: 返回一个无限长度的Stream,其元素由Supplier接口的提供。在Supplier是一个函数式
接口,只封装了一个get()方法,其用来返回任何泛型的值,该结果在不同的时间内,返回的可能是不同的数据
类型,没有特殊的要求。
Stream.generate(Supplier<T> s)	// 返回一个无限长度的Stream 
/*
这种情形通常用于随机数、常量的 Stream,或者需要前后元素间维持着某种状态信息的 Stream。把 Supplier
实例传递给 Stream.generate() 生成的 Stream,默认是串行(相对 parallel 而言)但无序的(相对ordered
而言)。
*/
Stream<Double> generateA = Stream.generate(new Supplier<Double>() {
    @Override
    public Double get() {
        return java.lang.Math.random();
    }
  });

Stream<Double> generateB = Stream.generate(()-> java.lang.Math.random()); 
Stream<Double> generateC = Stream.generate(java.lang.Math::random); 


// 3. iterate()方法: 
/*
iterate方法,其返回的也是一个无限长度的Stream,与generate方法不同的是,其是通过函数f迭代对给指定的
元素种子而产生无限连续有序Stream,其中包含的元素可以认为是:seed,f(seed),f(f(seed))无限循环。
*/ 
Stream.iterate(T seed, UnaryOperator<T> f) 
// 示例: 
Stream.iterate(1, item -> item + 1)
        .limit(10)
        .forEach(System.out::println); 
        // 打印结果:1,2,3,4,5,6,7,8,9,10 


// 4. empty()方法
// empty方法返回一个空的顺序Stream,该Stream里面不包含元素项。
import java.util.stream.Stream;

public class StreamEmptyExample {
    public static void main(String[] args) {
        // 创建一个空的Stream
        Stream<String> emptyStream = Stream.empty();

        // 打印空的Stream
        emptyStream.forEach(System.out::println);
    }
}
/*
	没有任何输出...
*/
// 5. 其他方法
Random.ints()
BitSet.stream()
Pattern.splitAsStream(java.lang.CharSequence)
JarFile.stream()

8.2 流的操作

把一个数据结构包装成Stream后,就要开始对里面的元素进行各类的操作了。常见的操作可以归类为如下:

  • Intermediate操作
    map(mapToInt、flatMap等)、filter、distinct、sorted、peek、limit、skip、parallel、sequential、unordered
  • Terminal操作
    forEach、forEachOrdered、toArray、reduce、collect、min、max、count、anyMatch、allMatch、noneMatch、findFirst、findAny、iterator
  • Short-circuiting操作
    anyMatch、allMatch、noneMatch、findAny、limit

详细介绍各种操作哦 ~ ,宝贝们,你们学不好编程的话,可以添加vx:LeKu_yuan私人陪跑。

8.2.1 map/flatMap

/* 
filter方法对原Stream按照指定条件过滤,在新建的Stream中,只包含满足条件的元素,将不满足条件的元素
过滤掉
*/
// 代码案例说明map
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class FileOperations {
    public static void main(String[] args) {
        String inputFile = "input.txt";
        String outputFile = "output.txt";

        try (BufferedReader reader = new BufferedReader(new FileReader(inputFile));
             BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) {

            // 使用流来读取文件内容,并将其处理后写入到另一个文件中
            reader.lines()
                    .map(line -> line.toUpperCase()) // 将每一行转换为大写
                    .forEach(line -> {
                        try {
                            writer.write(line);
                            writer.newLine();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });

            System.out.println("文件处理完成!");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 对flatMap说明:flatMap方法的作用是将流中的每个元素转换为一个流,并将这些流合并成一个流。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FlatMapExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("Hello", "World");

        List<String> letters = words.stream()
                .flatMap(word -> Arrays.stream(word.split(""))) // 将每个单词拆分成字母流
                .collect(Collectors.toList());

        System.out.println(letters);
    }
}
/**
* 在flatMap的使用中,我们首先调用words.stream()来获取单词的流。然后,对于每个单词,
* 我们使用 *Arrays.stream(word.split(""))将单词拆分成字符数组,并将每个字符数组转换为
*  一个字母流。
*/

8.2.2 filter

// filter方法对原stream按照指定条件过滤,在新建的stream中,只包含满足条件的元素,将不满足条件
// 的元素过滤掉。

// 代码演示:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FilterExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 过滤出所有偶数
        List<Integer> evenNumbers = numbers.stream()
                .filter(number -> number % 2 == 0)
                .collect(Collectors.toList());

        System.out.println(evenNumbers);
    }
}
// 输出结果为:[2, 4, 6, 8, 10]

8.2.3 sorted

Stream的排序通过sorted进行,它比数组的排序更强之处在于你可以首先对Stream进行各类map、filter、
limit、skip甚至distinct来减少元素数量后再排序,这能帮助程序明显缩短执行时间。
/* 无参: 无参形式的sorted方法会根据元素的自然顺序进行排序。如果流中的元素实现了Comparable接口,
 那么它们的自然顺序就是由compareTo方法定义的。*/
import java.util.Arrays;
import java.util.List;

public class SortedExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9, 3);

        // 对流中的元素进行排序
        List<Integer> sortedNumbers = numbers.stream()
                .sorted()
                .collect(Collectors.toList());

        System.out.println(sortedNumbers);
    }
}
// 输出结果为:[1, 2, 3, 5, 8, 9]


// 有参: 有参形式的sorted方法接受一个Comparator函数式接口作为参数,用于定义元素的排序规则。
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class SortedExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("cat", "apple", "banana", "dog");

        // 根据字符串长度对流中的元素进行排序
        List<String> sortedWords = words.stream()
                .sorted(Comparator.comparing(String::length))
                .collect(Collectors.toList());

        System.out.println(sortedWords);
    }
}
// 输出结果为:[cat, dog, apple, banana]

8.2.4 distinct

distinct 方法以达到去除掉原 Stream 中重复的元素,生成的新 Stream 中没有没有重复的元素
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class DistinctExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 4, 3, 5, 4, 6, 5);

        // 去除重复的元素
        List<Integer> distinctNumbers = numbers.stream()
                .distinct()
                .collect(Collectors.toList());

        System.out.println(distinctNumbers);
    }
}
// 输出结果为:[1, 2, 3, 4, 5, 6],这是去除重复元素后的整数列表

8.2.5 limit/skip

limit返回Stream的前面n个元素;skip则是扔掉前n个元素(它是由一个叫 subStream的方法改名而来)// limit代码案例:
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用lambda表达式和Stream API来限制元素数量
        List<Integer> limitedNumbers = numbers.stream()
                .limit(3) // 限制元素数量为3
                .collect(Collectors.toList());

        System.out.println(limitedNumbers); // 输出 [1, 2, 3]
    }
}

// skip代码案例:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用lambda表达式和Stream API来跳过指定数量的元素
        List<Integer> skippedNumbers = numbers.stream()
                .skip(2) // 跳过前2个元素
                .collect(Collectors.toList());

        System.out.println(skippedNumbers); // 输出 [3, 4, 5]
    }
}

8.2.6 Terminal操作

 1) forEach
forEach方法接收一个Lambda表达式,然后在Stream的每一个元素上执行该表达式。
注:forEach 不能修改自己包含的本地变量值,也不能用break/return之类的关键字提前结束循环。

2) findFirst
这是一个terminal兼short-circuiting操作,它总是返回Stream的第一个元素或者空。

3) reduce
这个方法的主要主要作用是把Stream元素组合起来。它提供一个起始值(种子),然后依照运算规则
(BinaryOperator),和前面Stream的第一个、第二个、第n个元素组合。从这个意义上说,字符串拼接、
数值的 sum、min、max、average都是特殊的reduce。

/* 代码案例说明reduce使用:*/
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用reduce方法求和
        int sum = numbers.stream()
                .reduce(0, (a, b) -> a + b);
        System.out.println("Sum: " + sum);

        // 使用reduce方法求乘积
        int product = numbers.stream()
                .reduce(1, (a, b) -> a * b);
        System.out.println("Product: " + product);

        // 使用reduce方法求最大值
        int max = numbers.stream()
                .reduce(Integer.MIN_VALUE, (a, b) -> a > b ? a : b);
        System.out.println("Max: " + max);
    }
}
/* 运行结果为:
	Sum: 15
	Product: 120
	Max: 5
*/

4) min/max
min和max的功能也可以通过对Stream元素先排序,再findFirst来实现,但前者的性能会更好为O(n),而
sorted的成本是O(nlogN)。同时它们作为特殊的reduce方法被独立出来也是因为求最大最小值是很常见的
操作。

5) Match
(1).allMatch:Stream 中全部元素符合传入的 predicate,返回 true(2).anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true(3).noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true;
注:它们都不是要遍历全部元素才能返回结果。例如allMatch只要一个元素不满足条件,
就skip剩下的所有元素,返回false6)match
Stream有三个match方法,从语义上说:
(1) allMatch: Stream中全部元素符合传入的predicate,返回true
(2) anyMatch: Stream中只要有一个元素符合传入的predicate,返回true
(3) noneMatch: Stream中没有一个元素符合传入的predicate,返回true;
注:它们都不是要遍历全部元素才能返回结果。例如allMatch只要一个元素不满足条件,就skip剩下的所有元
素,返回false
/*代码演示:allMatch、anyMatch、noneMatch*/
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用allMatch方法判断是否所有元素都大于0
        boolean allGreaterThanZero = numbers.stream()
                .allMatch(n -> n > 0);
        System.out.println("All greater than zero: " + allGreaterThanZero);

        // 使用anyMatch方法判断是否存在元素大于3
        boolean anyGreaterThanThree = numbers.stream()
                .anyMatch(n -> n > 3);
        System.out.println("Any greater than three: " + anyGreaterThanThree);

        // 使用noneMatch方法判断是否所有元素都小于0
        boolean noneLessThanZero = numbers.stream()
                .noneMatch(n -> n < 0);
        System.out.println("None less than zero: " + noneLessThanZero);
    }
}
/*
	All greater than zero: true
	Any greater than three: true
	None less than zero: true
*/

7) limit
limit方法将截取原stream,截取后stream的最大长度不能超过指定值N。如果原Stream的元素个数大于N,将
截取原Stream的前N个元素;如果原Stream的元素个数小于或等于N,将截取原Stream中的所有元素。
8) collect
将stream中的元素收集到一个集合或其他数据结构中

9) count: 返回stream的元素数量

10)toArray: 将stream中的元素转换为数组

11) findAny: 返回Stream中的任意一个元素。
/* java演示findAny代码 */
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用findAny方法获取流中的任意一个元素
        Optional<Integer> anyNumber = numbers.stream()
                .findAny();
        System.out.println("Any number: " + anyNumber.orElse(null));
    }
}

9. 补充optional接口的用法

说明:

  1. Optional接口是Java 8中引入的一个容器类,用于表示一个值存在或不存在的情况,它可以来解决空指针异常的问题,提供了一种更加优雅的方式处理可能为空的值。
  2. Optional类的主要作用是在某个值可能为空的情况下,提供一种简洁、安全的方式来处理这个值。它可以被看作是一个包装类,可以包装一个可能为空的值。通过使用Optional类,可以避免在代码中大量使用null检查和空指针异常处理。
// 常见的 api用法:
of(value) 创建一个包含指定值的Optional对象
empty(): 创建一个空的Optional对象
isPresent(): 判断Optional对象中是否包含值
get(): 获取Optional对象中的值,如果值不存在则会抛出NoSuchElementException异常
orElse(defaultValue): 获取Optional对象中的值,如果值不存在则返回默认值
orElseGet(Supplier): 获取Optional对象中的值,如果值不存在则通过提供的Supplier函数生成一个默认值
orElseThrow(ExceptionSupplier): 获取Optional对象中的值,如果值不存在则抛出指定的异常

》》》》》》》》》》》》》》》分》隔》行》》》》》》》》》》》》》》》》》》

ofNullable(T value): 将指定的值包装成Optional对象。如果value为null,则返回一个空的Optional对象;
					 否则返回一个包含value的Optional对象。

get(): 如果Optional对象中的值存在,则返回该值;否则抛出NoSuchElementException异常。

isPresent(): 判断Optional对象中是否存在值。如果存在则返回true,否则返回falseifPresent(Consumer<? super T> consumer): 如果Optional对象中的值存在,则执行指定的操作;
										否则不执行任何操作。
// 获取值的操作,根据没有值,执行不同的操作
// orElse(T other):没有值返回指定的值other
orElse(T other): 如果Optional对象中的值存在,则返回该值;否则返回指定的默认值other。
//没有值的话使用supplier提供一个值
orElseGet(Supplier<? extends T> supplier): 如果Optional对象中的值存在,则返回该值;
							否则通过指定的Supplier函数式接口提供一个默认值。
// 没有值的话抛出一个异常
orElseThrow(Supplier<? extends X> exceptionSupplier): 如果Optional对象中的值存在,则返回该值;
							否则通过指定的Supplier函数式接口抛出一个异常。

map(Function<? super T, ? extends U> mapper): 如果Optional对象中的值存在,
		则对其进行映射并返回一个包含映射结果的Optional对象;否则返回一个空的Optional对象。

flatMap(Function<? super T, Optional> mapper): 如果Optional对象中的值存在,则对其进行映射
		并返回一个包含映射结果的Optional对象;否则返回一个空的Optional对象。与map()方法
		不同的是,flatMap()方法的映射函数返回值必须是Optional对象。

filter(Predicate<? super T> predicate): 如果Optional对象中的值存在,并且满足指定的条件predicate,
			则返回该Optional对象;否则返回一个空的Optional对象。

// 代码演示Optional:
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        String name = "John";
        Optional<String> optionalName = Optional.of(name);

        // 检查Optional对象是否包含值
        if (optionalName.isPresent()) {
            System.out.println("Name is present: " + optionalName.get());
        } else {
            System.out.println("Name is not present");
        }

        // 获取Optional对象中的值,如果值不存在则返回默认值
        String defaultValue = "Unknown";
        String value = optionalName.orElse(defaultValue);
        System.out.println("Value: " + value);

        // 获取Optional对象中的值,如果值不存在则通过提供的函数生成一个默认值
        String generatedValue = optionalName.orElseGet(() -> generateDefaultValue());
        System.out.println("Generated Value: " + generatedValue);

        // 获取Optional对象中的值,如果值不存在则抛出指定的异常
        try {
            String result = optionalName.orElseThrow(() -> new IllegalArgumentException("Name is not
           											 present"));
            System.out.println("Result: " + result);
        } catch (IllegalArgumentException e) {
            System.out.println("Exception: " + e.getMessage());
        }
    }

    private static String generateDefaultValue() {
        System.out.println("Generating default value");
        return "Default";
    }
}

/*输出结果为:
	Name is present: John
	Value: John
	Generating default value
	Generated Value: John
	Result: John
*/

10.总结流操作

1.可以使用filter、distinct、skip和limit对流进行筛选和切片;
2.可以使用map和flatMap提取或转换流中的元素;
3.可以使用findFirst和findAny方法查找流中的元素,你可以使用allMatch、noneMatch和anyMatch方法让流匹配给定的谓语;
4.上述方法都利用 了短路:找到结果就立刻停止计算,并没有处理整个流;
5.可以使用reduce方法将流中的所有元素迭代合并成为一个结果,例如求和或查询最大的元素;
6.filter和map等操作都是无状态的,它们并没有存储任何状态。reduce等操作要存储状态才能计算出一个值,sorted和distinct等操作也要存储状态,因为他们需要把流中的所有元素缓存起来才能返回一个新的流,这种操作叫做有状态操作;
7.流有三种基本原始类型特化:intStream、doubleStream和LongStream,他们的操作也有相应的特化
8.流不仅可以从集合创建,也可以从值、数组、文件以及iterate与generate等特定方法创建。

11. 小结一下

Stream的特性归纳如下:

  1. 不是数据结构;
  2. 没有存储结构,它只是用操作管道从source(数据结构、数组、generator、function、IO channel)抓取数据
  3. 它也绝不修改自己所封装的底层数据结构的数据。例如Stream的filter操作会产生一个不包含被过滤元素的新Stream,而不是从source删除那些元素。
  4. 所有stream的操作必须以lambda表达式为参数;
  5. 不支持索引访问
  6. 你可以请求第一个元素,但无法请求第二个、第三个,或最后一个。
  7. 很容易生成数组或者list;
  8. 惰性化;
  9. 很多Stream操作是向后延迟的,一直到它弄清楚了最后需要多少数据才会开始。
  10. Intermediate操作永远是惰性化的
  11. 并行能力
  12. 当一个stream是并行的,就不需要在写多线程代码,所有对它的操作会自动并行进行的;
  13. 可以是无限的。集合有固定大小、stream则不必,limit(n)和findFirst()这类的short-circuiting操作可以对无限的stream进行运算并很快完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值