java成神之——Stream和Optional

Posted 叶家伟的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java成神之——Stream和Optional相关的知识,希望对你有一定的参考价值。

Stream流

基本使用

Stream<String> myStream = Stream.of("a", "", "b", "c", "d");
myStream.filter(item -> item!="").map(String::toUpperCase).sorted().forEach(System.out::println); // ABCD

使用流注意点:
    如果一个流没有调用终端方法,那么流的其他操作都不会执行
    
    终端方法如:count() collect() forEach()

流关闭

流用来操作文件的时候才需要手动关闭,单独使用Stream不需要关闭

try (Stream<String> lines = Files.lines(Paths.get("C:\Users\26401\Desktop\demo.txt")).onClose(() -> System.out.println("流自动关闭了"))) {
    lines.forEach(System.out::println);
}

平行流

处理顺序:

    上面介绍的例子都是顺序流,但是如果对元素的顺序不要求的时候可以使用平行流,开启多核心多线程加速处理速度

    List<Integer> list = Arrays.asList(1,2,3,4,5);
    list.stream().forEach(System.out::println);

    System.out.println("---------------");
    list.parallelStream().forEach(System.out::println);

    1 2 3 4 5
    ---------------
    3 5 4 2 1

使用平行流注意点:

    在开发网络程序的时候,使用平行流会显著降低性能,因为只有一个分支-合并流
    除了这一点以外,平行流的性能根据cpu的核心数决定
    Stream.of("a", "b").parallel();
    Arrays.asList("a", "b").parallelStream();

流重用

流本身是不能重用的,但是可以使用iterator来实现重用

Iterable<Integer> iterable = () -> IntStream.range(1, 10).map(i -> ++i).iterator();
for (Integer item : iterable) {
    System.out.println(item);
}

iterator转换成流

Iterator<String> iterator = Arrays.asList("A", "B", "C").iterator();
Spliterator<String> spliterator = Spliterators.spliteratorUnknownSize(iterator, 0);
Stream<String> stream = StreamSupport.stream(spliterator, false);
stream.forEach(System.out::println);

分组计数

Stream
.of("a", "b", "a", "c")
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.forEach(System.out::println);

a=2
b=1
c=1

无限流

方式一:
    IntStream naturalNumbers = IntStream.iterate(1, x -> x + 1);
    naturalNumbers.limit(5).forEach(System.out::println);

方式二:
    Stream<Double> infiniteRandomNumbers = Stream.generate(Math::random);
    infiniteRandomNumbers.limit(10).forEach(System.out::println);

流转集合

方式一:
    List<String> list = Stream.of("a", "b", "c").collect(Collectors.toList());

方式二:
    List<String> list = Stream.of("a", "b", "c").collect(Collectors.toCollection(ArrayList::new));

方式三:
    List<String> list = Stream.of("a", "b", "c").collect(Collectors.toCollection(() -> new ArrayList<>()));

压缩流

List<String> list1 = Arrays.asList("a", "b");
List<String> list2 = Arrays.asList("c", "d");
List<String> list3 = Arrays.asList("e", "f");

List<String> joinList = Stream.of(list1, list2, list3).flatMap(Collection::stream).collect(Collectors.toList());
或者
List<String> joinList = Stream.of(list1, list2, list3).flatMap(List::stream).collect(Collectors.toList());
// ["a","b","c","d","e","f"]

统计数值流

IntSummaryStatistics
LongSummaryStatistics
DoubleSummaryStatistics

IntSummaryStatistics stats = Stream.of(1, 2, 3).mapToInt(x -> x).summaryStatistics();

stats.toString(); // IntSummaryStatistics{count=3, sum=6, min=1, average=2.000000, max=3}

集合转换流遍历

String[] names = { "Jon", "Darin", "Bauke", "Hans", "Marc" };
IntStream.range(0, names.length).mapToObj(i -> String.format("#%d %s", i + 1, names[i])).forEach(System.out::println);

流拼接

Stream.concat(Arrays.asList("a", "b", "c").stream(), Arrays.asList("d", "e", "f").stream());

reduce

reduce方法的作用类似于码积木

OptionalInt result = IntStream.range(1, 10).reduce((b,l) -> b+l);   // 45
int result = IntStream.range(1, 10).reduce(100, (b,l) -> b+l);      // 145

使用流生成随机字符串

SecureRandom 实例化开销很大,可以使用setSeed重置

下面生成的随机字符串只包含数字和字母

    SecureRandom sr = new SecureRandom();

    sr.setSeed(sr.generateSeed(20));
    int length = 20;
    Stream<Character> randomCharStream = sr.ints(Character.MIN_CODE_POINT,Character.MAX_CODE_POINT).mapToObj(i -> (char)i).filter(c -> c >= ‘0‘ && c <= ‘z‘ && Character.isLetterOrDigit(c)).limit(length);
    String randomString = randomCharStream.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString();

流的包装流

几种包装流

PrintWriter                                 自动调用OutputStreamWriter,允许写原始数据类型和字符串

OutputStreamWriter                          将OutputStreams转换成Writers从而来处理字符而不是字节

BufferedOutputStream/BufferedInputStream    OutputStreams处理字节是一个一个的来处理的,这个流是一块儿一块儿来处理的

DeflaterOutputStream/DeflaterInputStream    压缩数据

InflaterOutputStream/ InflaterInputStream   解压数据

CipherOutputStream/ CipherInputStream       加密数据

DigestOutputStream/ DigestInputStream       解密数据

CheckedOutputStream/CheckedInputStream

DataOutputStream/ DataInputStream           写字节

PrintStream                                 写字节

包装流写字符到文件

FileOutputStream stream = new FileOutputStream("C:\Users\26401\Desktop\demo.txt");
try(PrintWriter writer = new PrintWriter(new BufferedOutputStream(stream))){
    writer.write("我是包装流写的字符串");
}

加密和压缩数据

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");         // “算法/工作模式/填充模式”
SecretKey secretKey = new SecretKeySpec("abcdefghigklmnop".getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
try(BufferedOutputStream outputStream = new BufferedOutputStream(new DeflaterOutputStream(new CipherOutputStream(new FileOutputStream("C:\Users\26401\Desktop\demo.txt"), cipher)));) {
    outputStream.write("加密数据".getBytes());
}

Optional

Optional的常用方法

Optional的使用方式类似于Stream

区别在于,方法不会管有没有调用终端方法,只会立即执行

ofNullable      如果值是null,则返回一个空的Optional
map
filter
get             获取值
orElse          默认值
orElseGet       默认值
orElseThrow     默认抛出异常

Optional的基本使用

String value = "abc";
String str = Optional.ofNullable(value).map(String::toUpperCase).orElse("NONE"); // ABC

String value = null;
String str = Optional.ofNullable(value).orElseGet(() -> "defaultValue");         // defaultValue

String value = null;
String str = Optional.ofNullable(value).orElseThrow(IllegalArgumentException::new);

int value = 123;
int result = Optional.ofNullable(value).filter(item -> item == 123).get();

原始数据类型

OptionalDouble
OptionalInt
OptionalLong 

结语

本文章是java成神的系列文章之一

如果你想知道,但是本文没有的,请下方留言

我会第一时间总结出来并发布填充到本文

以上是关于java成神之——Stream和Optional的主要内容,如果未能解决你的问题,请参考以下文章

java成神之——安全和密码

成神之Java之路

java成神之——java中string的用法

java成神之——HttpURLConnection访问api

springboot成神之——拦截器

java成神之——Fork/Join基本使用