zoukankan      html  css  js  c++  java
  • 流式编程

    概念:

    使用流,无需迭代集合中的元素,就可以从管道提取和操作元素。这些管道通常被组合在一起,形成一系列对流进行操作的管道。

    在大多数情况下,将对象存储在集合中是为了处理他们,因此你将会发现你将把编程的主要焦点从集合转移到了流上。

    Java 8 采用的解决方案是:在接口中添加被 default默认)修饰的方法。通过这种方案,设计者们可以将流式(stream)方法平滑地嵌入到现有类中。流方法预置的操作几乎已满足了我们平常所有的需求。流操作的类型有三种:创建流,修改流元素(中间操作, Intermediate Operations),消费流元素(终端操作, Terminal Operations)。最后一种类型通常意味着收集流元素(通常是到集合中)。

    流创建

    使用StreamOf可以轻松将数组转换成流。

    void forEach(Consumer<? super T> action);这个是Stream类中的一个方法,参数是函数式接口,我们传一个实现实现类的方法即可。
    @FunctionalInterface
    public interface Consumer<T> {
    // streams/StreamOf.java
    import java.util.stream.*;
    public class StreamOf {
        public static void main(String[] args) {
            Stream.of(new Bubble(1), new Bubble(2), new Bubble(3))
                .forEach(System.out::println);
            Stream.of("It's ", "a ", "wonderful ", "day ", "for ", "pie!")
                .forEach(System.out::print);
            System.out.println();
            Stream.of(3.14159, 2.718, 1.618)
                .forEach(System.out::println);
        }
    }

    使用stream()可以轻松将集合转换成流

    map方法可以作为元素过滤器使用

    public class CollectionToStream {
        public static void main(String[] args) {
    /*        List<Bubble> bubbles = Arrays.asList(new Bubble(1), new Bubble(2), new Bubble(3));
            System.out.println(bubbles.stream()
                    .mapToInt(b -> b.i)
                    .sum());*/
    
            Set<String> w = new HashSet<>(Arrays.asList("It's a wonderful day for pie!".split(" ")));
            w.stream()
                    .map(x -> x + " ")
                    .forEach(System.out::print);
            System.out.println();
    
            Map<String, Double> m = new HashMap<>();
            m.put("pi", 3.14159);
            m.put("e", 2.718);
            m.put("phi", 1.618);
            m.entrySet().stream()
                    .map(e -> e.getKey() + ": " + e.getValue())
                    .forEach(System.out::println);
        }
    }

    随机数产生

    boxed()方法会将基本类型的数据包装成为对应的装箱类型,进而能被泛型方法show()调用。

    public class RandomGenerators {
        public static <T> void show(Stream<T> stream) {
            stream
                    .limit(4)
                    .forEach(System.out::println);
            System.out.println("++++++++");
        }
    
        public static void main(String[] args) {
            Random rand = new Random(47);
            show(rand.ints().boxed());
            show(rand.longs().boxed());
            show(rand.doubles().boxed());
            // 控制上限和下限:
            show(rand.ints(10, 20).boxed());
            show(rand.longs(50, 100).boxed());
            show(rand.doubles(20, 30).boxed());
            // 控制流大小:
            show(rand.ints(2).boxed());
            show(rand.longs(2).boxed());
            show(rand.doubles(2).boxed());
            // 控制流的大小和界限
            show(rand.ints(3, 3, 9).boxed());
            show(rand.longs(3, 12, 22).boxed());
            show(rand.doubles(3, 11.5, 12.3).boxed());
        }
    }

     Random 为任意对象集合创建 Supplier

     当你用 Collectors.joining()作为 collect() 的参数时,将得到一个String 类型的结果,该结果是流中的所有元素被joining()的参数隔开。

    public class RandomWords implements Supplier<String> {
        List<String> words = new ArrayList<>();
        Random rand = new Random(47);
        RandomWords(String fname) throws IOException {
            List<String> lines = Files.readAllLines(Paths.get(fname));
            // 略过第一行
            for (String line : lines.subList(1, lines.size())) {
                for (String word : line.split("[ .?,]+"))
                    words.add(word.toLowerCase());
            }
        }
        public String get() {
            return words.get(rand.nextInt(words.size()));
        }
    /*    @Override
        public String toString() {
            return words.stream()
                    .collect(Collectors.joining(" "));
        }*/
        public static void main(String[] args) throws Exception {
            System.out.println(
                    Stream.generate(new RandomWords("D:\myGitHub\Java\SingaporeJava\project\versionjdk18\stream\src\Cheese.dat"))
                            .limit(10)
                            .collect(Collectors.joining(" ")));
        }
    }

    流的建造者模式

    在建造者模式(Builder design pattern)中,首先创建一个 builder 对象,然后将创建流所需的多个信息传递给它,最后builder 对象执行”创建“流的操作。Stream 库提供了这样的 Builder。在这里,我们重新审视文件读取并将其转换成为单词流的过程。

    public class FileToWordsBuilder {
        Stream.Builder<String> builder = Stream.builder();
        
        public FileToWordsBuilder(String filePath) throws Exception {
            Files.lines(Paths.get(filePath))
                 .skip(1) // 略过开头的注释行
                 .forEach(line -> {
                      for (String w : line.split("[ .?,]+"))
                          builder.add(w);
                  });
        }
        
        Stream<String> stream() {
            return builder.build();
        }
        
        public static void main(String[] args) throws Exception {
            new FileToWordsBuilder("Cheese.dat")
                .stream()
                .limit(7)
                .map(w -> w + " ")
                .forEach(System.out::print);
        }
    }

    Arrays

    Arrays 类中含有一个名为 stream() 的静态方法用于把数组转换成为流。

    public class ArrayStreams {
        public static void main(String[] args) {
            Arrays.stream(new double[] { 3.14159, 2.718, 1.618 })
                .forEach(n -> System.out.format("%f ", n));
            System.out.println();
            
            Arrays.stream(new int[] { 1, 3, 5 })
                .forEach(n -> System.out.format("%d ", n));
            System.out.println();
            
            Arrays.stream(new long[] { 11, 22, 44, 66 })
                .forEach(n -> System.out.format("%d ", n));
            System.out.println();
            
            // 选择一个子域:
            Arrays.stream(new int[] { 1, 3, 5, 7, 15, 28, 37 }, 3, 6)
                .forEach(n -> System.out.format("%d ", n));
        }
    }
    

      

     使用正则表达式分割字符串生成流

    public class FileToWordsRegexp {
        private String all;
        public FileToWordsRegexp(String filePath) throws Exception {
            all = Files.lines(Paths.get(filePath))
            .skip(1) // First (comment) line
            .collect(Collectors.joining(" "));
        }
        public Stream<String> stream() {
            return Pattern
            .compile("[ .,?]+").splitAsStream(all);
        }
        public static void
        main(String[] args) throws Exception {
            FileToWordsRegexp fw = new FileToWordsRegexp("Cheese.dat");
            fw.stream()
              .limit(7)
              .map(w -> w + " ")
              .forEach(System.out::print);
            fw.stream()
              .skip(7)
              .limit(2)
              .map(w -> w + " ")
              .forEach(System.out::print);
        }
    }
    String str = "wo ai,ni?zhong.guo";
    Pattern.compile("[ .,?]+").splitAsStream(str).map(w -> w + " ").forEach(System.out::print);
  • 相关阅读:
    Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法
    Python2.x与Python3.x的区别
    oracle锁机制
    传统解析xml的方式
    利用jdbc连接oracle数据库
    XML的解析方式(DOM、SAX、StAX)
    软件或jar包等名字里的GA意思
    windows下nginx的安装及使用
    是时候选择一款富文本编辑器了(wangEditor)
    Golang代码实现HTTPs(HTTPS证书生成和部署)
  • 原文地址:https://www.cnblogs.com/Lambquan/p/13657000.html
Copyright © 2011-2022 走看看