Java8的流特性-常用操作(例)

public class StreamMethods {

/**
 * 流的过滤
 * 大部分流操作的结果仍然是一个流,所以我们可以链式调用
 */
public void testStreamFilter() {
    List<Integer> integers = new ArrayList<>();
    integers.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8));
    //使用流类库
    integers = integers.stream().filter(i -> i > 5).collect(Collectors.toList());
    System.out.println(integers);
}

/**
 * 流的映射
 *  类似于SQL中的select,可以将一组元素转换成另一种元素。
 *  下面的例子将一组整数转换为平方。这是一个简单的例子,实际场合中常常需要将一组对象流转换为另一组对象。
 */
public void testStreamMap() {

    List<Integer> integers = Stream.of(1, 2, 3, 4)
            .map(i -> i * i)
            .collect(Collectors.toList());
    System.out.println(integers);
}

/**
 * 流的平整映射
 *  有时候需要将多个流的结果合并为一个流,这时候需要使用平整映射。
 */
public void testStreamFlatMap() {
    List<Integer> integers = Stream.of(Arrays.asList(1, 2, 3, 4), Arrays.asList(5, 6))
            .flatMap(n -> n.stream())
            .collect(Collectors.toList());
    System.out.println(integers);
}

/**
 * 流求最大或最小值
 */
public void testStreamMaxOrMin() {

    int min = Stream.of(1, 23, 4, 50, 8888)
            .min(Comparator.comparingInt(i -> i))
            .get();
    int max = Stream.of(0, 1, 2, 5, 89, 465, 45, 666, 8888)
            .max(Comparator.comparingInt(i -> i)).get();
    System.out.println(String.format("max:%d,min:%d", max, min));
}


/**
 * TODO 不太懂这个接口 流的通用迭代 reduce
 */
public void testStreamReduce() {

    int sum = Stream.of(1, 2, 3, 4, 5)
            .reduce((acc, e) -> acc + e).get();
    System.out.println(String.format("sum:%d", sum));

    int product = Stream.of(1, 2, 3, 4, 5)
            .reduce(1, (acc, e) -> acc * e);
    System.out.println(String.format("product:%d", product));
}

/**
 * 流的一些谓词特性
 * allMatch:当所有条件满足时返回true
 * anyMatch:只要有一个元素满足就返回true
 * noneMatch:当没有元素返回时返回true
 * distinct:去掉重复的元素
 * limit:保留流的前几个元素
 * skip:跳过前几个元素而获取之后的所有元素
 */
public void testStreamPredicate() {
    boolean allMatch = Stream.of(1, 2, 3, 4, 5).allMatch(i -> i > 3);
    System.out.println("allMatch: " + allMatch);

    boolean anyEqual = Stream.of(1, 2, 3, 4, 5).anyMatch(i -> i >= 2);
    System.out.println("anyMatch: " + anyEqual);

    boolean noneEqual = Stream.of(1, 2, 3, 4, 5).noneMatch(i -> i < 0);
    System.out.println("noMatch: " + noneEqual);

    List<Integer> list = Stream.of(1, 2, 3, 4, 2, 2, 4, 3, 1, 2, 4, 3, 1, 2)
            .distinct()
            .collect(Collectors.toList());
    System.out.println(list);

    String list1 = Stream.of(1, 2, 3, 4, 5, 6)
            .limit(3)
            .map(String::valueOf)
            .collect(Collectors.joining(", ", "[", "]"));
    System.out.println(list1);

    String list2 = Stream.of(1, 2, 3, 4, 5, 6)
            .skip(3)
            .map(String::valueOf)
            .collect(Collectors.joining(", ", "[", "]"));
    System.out.println(list2);
}

/**
 * 基本类型流
 * 由于Java存在一个基本类型装箱拆箱的过程,所以会有性能开销。
 * 为了避免这些开销,流类库针对常见的基本类型int、long、double做了特殊处理,
 * 为它们单独准备了一些类和方法。
 * 注意:对于一些方法也有基本类型的版本,可以将一个对象流转换为对应的基本类型,
 * 这些方法的命名规则是方法名+To+基本类型。如果需要处理大量数据的基本类型流,
 * 可以考虑使用这些方法。
 */
public void testStreamPrimitiveType() {

    IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
    LongStream longStream = LongStream.of(1, 2, 3, 4, 5);
    DoubleStream doubleStream = DoubleStream.of(10, 2.0, 3.0);

    int sum = Stream.of(1, 2, 3, 4, 5)
            .mapToInt(i -> i)
            .reduce(0, (acc, e) -> acc + e);
    //.sum();
    System.out.println("sum :" + sum);
}

/**
 * 流的收集器(collect()方法)
 *   使用流类库的最后一步就是将流转换为我们需要的集合了,这就需要用到收集器。
 *   收集数据的最后一步需要调用collect方法,它的参数是java.util.stream.Collector类的静态方法。
 *   听起来是不是有点奇怪,实际上,接受的是这些方法的返回值。
 *   例如toList()方法实际上是这样的,返回的是Collector对象,然后由collect方法处理,获取最后的集
 *   合。
 *   源代码示例
 *   public static <T>Collector<T, ?, List<T>> toList() {
 *     return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
 *     (left, right) -> { left.addAll(right); return left; },
 *     CH_ID);
 *    }
 */

/**
 * 通过收集器获得流的集合
 */
public void testGetStreamCollections(){
    List<Integer> integers = Stream.of(1,2,3,4,5)
            .collect(Collectors.toList());
    System.out.println("list: "+integers);

    Set<Integer> set = Stream.of(1,2,2,3,4,5)
            .collect(Collectors.toSet());
    System.out.println("set: "+set);

    //使用自己希望的集合(可以构造成map集合或concurrentMap集合)
    ArrayList<Integer> integerArrayList = Stream.of(1,2,3)
            .collect(Collectors.toCollection(ArrayList::new));
    System.out.println("integerArrayList: "+integerArrayList);

}

/**
 * 通过收集器获取流的值
 *   收集器不仅可以获得集合,还可以由流获取一个值,
 *   这可以通过调用maxBy、minBy、averageXXX和summingXXX方法来实现
 */
public void testGetStreamValue(){
    int max = Stream.of(1,2,3,4)
            .collect(Collectors.maxBy(Comparator.comparing(i->i)))
            .get();
    int min = Stream.of(1,2,3,4)
            .collect(Collectors.minBy(Comparator.comparing(i->i)))
            .get();
    double average = Stream.of(1,2,3,4)
            .collect(Collectors.averagingInt(Integer::intValue));
    int sum = Stream.of(1,2,3,4)
            .collect(Collectors.summingInt(i->i));
    System.out.println(
            String.format("max:%d,min:%d,average:%f,sum:%d", max, min, average, sum));

    /**
     * 有时候需要将流的数据组合为一个字符串,这需要joining收集器,它的三个参数分别是分隔符、前缀和后缀。
     * 当然由于它需要字符序列,所以这里还需要用map方法将整数流转换为字符串流。
     */
    String string = Stream.of(1,2,3,4,5)
            .map(String::valueOf)
            .collect(Collectors.joining(", ","[","]"));
    System.out.println("string :"+string);

    /**
     * 还有一个简单的收集器,作用就是计数,需要注意的是计数返回的结果是long类型就行了。
     * 这个收集器的主要作用是和其他收集器一起完成复杂的功能。
     */
    Long count = Stream.of(1,2,3,4,5,6,7,8)
            .collect(Collectors.counting());
           // .count();
    System.out.println("count: "+count);
}

/**
 * 流的数据分块
 */
public void testStreamDataPartition() {
    Map<Boolean, List<Integer>> map = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
            .collect(Collectors.partitioningBy(i -> i % 2 == 0));
    System.out.println("map: " + map);
}

/**
 * 流的数据分组
 *   类似于SQL中的group by语句。下面的例子将流按照数组个位数分为好几组
 */
public void testDataGrouping() {
    Map<Integer, List<Integer>> map = Stream.of(21, 32, 43, 54, 11, 33, 22)
            .collect(Collectors.groupingBy(i -> i % 10));
    System.out.println("map: "+map);
}

/**
 * 流的组合收集器
 *   如果问题比较复杂,还可以将多个收集器组合起来使用,一些收集器有重载的版本,支持第二个收集器,
 *   可以用来实现这个功能。就拿前面那个数据分组的例子来说,这次我不仅要分组,
 *   而且只需要每组的十位数字,那么就可以这样写。
 *   groupingBy的第二个参数可以使用mapping收集器,mapping这里的作用和流操作的map类似,
 *   将流再次进行映射,然后收集结果作为最后Map的键值对。
 */
public void testGroupCollect(){

    //按个位数字进行分组,然后只获取十位上的数字
    Map<Integer, List<Integer>> map = Stream.of(21, 32, 43, 54, 11, 33, 22)
            .collect(Collectors.groupingBy(i -> i % 10,
                    Collectors.mapping(i -> i / 10,Collectors.toList())));
    System.out.println("map: "+map);

    //按个位数字分组,然后然后求各组的和
    Map<Integer,Integer> map1 = Stream.of(21,32,43,54,11,33,22)
            .collect(Collectors.groupingBy(i->i%10,Collectors.summingInt(i->i)));
    System.out.println("map1: "+map1);
}


/**
 * 关于流的其它特性
 */
public void testOther(){

    /**
     * *   所有的流操作都是惰性的,也就是说直到最后调用收集器的时候,整个流操作才开始进行。
     *   在这之前,你的流操作只不过类似于SQL的执行计划,这时候还没有真正执行程序。所以下面的代码什么都不会输出。
     */
    Stream.of(1,2,3,4,5)
            .filter(i->i>1)
            .filter(i->{
                System.out.println("i: "+i);
                return i<=3;
            });

    /**
     * 如果进行了很多流操作,流类库会不会对流进行多次迭代,导致程序速度很慢呢?
     * 这个担心也是多余的,流类库经过优化,会保证迭代以最少的次数进行。
     * 所以下面的代码输出结果是122334455,这说明流只迭代了一次。
     */
    List<Integer> integers = Stream.of(1, 2, 3, 4, 5)
            .filter(i -> {
                System.out.print(i);
                return i > 1;
            })
            .filter(i -> {
                System.out.print(i);
                return i <= 3;
            })
            .collect(Collectors.toList());
    System.out.println(integers);
}

/**
 * 流的循环
 */
public void testForLoop(){

    /**
     * 流的循环,相当于for循环
     */
    IntStream.range(0, 3)
            .forEach(i -> System.out.print(i));

}

/**
 * 流的数据并行化
 *   需要注意并不是说并行化之后,速度就一定会比串行化快,
 *   这需要根据当前系统、机器、执行的数据流大小来进行综合评估。
 *   ArrayList这类容器就比较容易并行化,而HashMap并行化就比较困难。
 */
public void testStreamParallel(){

    List<Integer> integers = IntStream.range(1, 101)
            .parallel()
            .filter(i -> i % 2 == 0)
            .boxed()
            .collect(Collectors.toList());
    System.out.println("integers :"+integers);
}

}

转载于:https://my.oschina.net/PrivateO2/blog/1618042

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值