您的位置:首页 > 编程语言 > Java开发

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

2018-02-03 17:18 447 查看
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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java ASList