一、前提
什么是流?在用JDK1.8的你肯定知道我就不多bb了。本篇主要介绍一下内容:
- 流的创建
- 流的操作
- 流的结束
听上去是不是很弟弟,别急,看完这篇,让你用流信手拈来。?
二、流基本介绍
什么是流
- JDK8提供的对集合数据进行处理的一种方式
- 流中的元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算
- 数据源流的来源。 可以是集合,数组,I/O channel, 产生器generator 等
- 有聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等
流的特点
- 一个流只能使用一次
- Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style),这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)
- 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代, Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现
串行流和并行流
顾名思义,串行流是一个个的执行,相当于单线程,并行流是并行执行,相当于多线程。
- 创建串行流:stream()
- 创建并行流:parallelStream()
根据实际测试,在数据量比较大的时候,并行流的速度快串行流1.5到3倍,看实际需求有所不同。
三、正文
好,前面都是对流一点都不知道的人说的废话,下面进入正文
1.各个容器类实现Stream的方式
本节覆盖了日常能用到的容器、数组、IO创建流的方式:
@Test
public void getStreamTest()
{
/**
* {@code Collection}在JDK1.8版本实现了Stream()方法和parallelStream()方法,
* 所有实现Collection的容器类通过调用stream()方法或者 parallelStream()
*/
// list
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.stream();
// Set
Set<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.stream();
// ArrayList
ArrayList<Integer> arrList = new ArrayList<>();
arrList.add(1);
arrList.add(2);
arrList.stream();
// Vector
Vector<Integer> vector = new Vector<>();
vector.add(1);
vector.add(2);
vector.stream();
// Queue
Queue<Integer> queue = new ArrayBlockingQueue<>(12);
queue.add(1);
queue.add(2);
queue.stream();
// Stack
Stack<Integer> stack = new Stack<>();
stack.add(1);
stack.add(2);
stack.stream();
// Map 通过调用map的entrySet()方法,获取Set再调用stream()
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.entrySet().stream();
/**
* {@code Arrays}在JDK1.8中加入了stream系列方法, 数组可以调用Arrays.stream(T []
* array)实现流,同时还有参数不同的stream函数用来截取数组
*/
// 数组
String[] arr = {"a", "b", "c"};
Arrays.stream(arr);
// 值,直接将值转变成流对象
Stream.of("a", "b", "c");
// 从IO获取流
try (
Stream<String> lines = Files.lines(Paths.get("文件路径名"), Charset.defaultCharset())
)
{
// 可对lines做一些操作
}
catch (IOException e)
{}
}
2.流的常用方法
@Test
public void streamMethodTest()
{
/**
* @decription 过滤器filter
* @param 一个返回true或者false的lambda表达式
* @return 筛选出返回结果为true的元素
*/
Stream.of(1, 2, 3).filter(a ->
{
return a.equals(1);
}).count();
/**
* @description 去重
* @return the new stream
*/
Stream.of(1, 2, 2, 3).distinct();
/**
* @decription 截取前n个元素
* @return the new stream
*/
Stream.of(1, 2, 3).limit(2);
/**
* @decription 跳过前n个元素
* @return the new stream
*/
Stream.of(1, 2, 3).skip(2);
/**
* @decription map() 一对一映射 输入一个元素,按照给定的规则处理该元素
*/
Stream.of("a", "b", "c").map(a ->
{
return a.toUpperCase();
}).map(String::toLowerCase);
/**
* @description flatMap() 将流扁平化,说人话就是将流中最基层的元素抽出来为单独的流,eg:
* List<List<Integer>>
* 类型的,会把最底层的Integer抽取出来,和map()不同的是map()将List<Integer>视为一个流进行处理
*/
// 写法1
Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6, 7)).flatMap(Collection::stream).map(a ->
{
// 此时 a就只是Integer了
return a.byteValue();
});
// 写法2
Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6, 7)).flatMap(l ->
{
return l.stream();
}).map(a ->
{
return a.byteValue();
});
/**
* @description 是否匹配任意元素,有任意一个符合为true
*/
Stream.of(1, 2, 3).anyMatch(a ->
{
return a.equals(1);
});
/**
* @description 是否匹配所有元素
*/
Stream.of(1, 2, 3).allMatch(a ->
{
return a.equals(1);
});
/**
* @description 是否所有元素都不匹配
*/
Stream.of(1, 2, 3).noneMatch(a ->
{
return a.equals(1);
});
/**
* @description 从流中返回任意元素,返回结果放在Optional对象中(实测怎么感觉就是findFirst())
*/
Stream.of(1, 2, 3).findAny();
/**
* @description 返回第一个元素,返回结果放在Optional对象中
*/
Optional<Integer> res = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4)).flatMap(Collection::stream)
.findFirst();
res.ifPresent(System.out::print);
/**
* @description reduce 自定义lambda表达式求和 以
* identity为初始值,对流中的所有元素执行lambda表达式求和
*/
Stream.of(1, 2, 3).reduce(0, (a, b) ->
{
return a + b;
});
}
3.普通流到数值流的转换
@Test
public void test3()
{
Stream.of(1, 2, 3).mapToDouble(Double::valueOf);
Stream.of(1, 2, 3).mapToLong(Long::valueOf);
}
4.Stream收集器—优雅的结束stream
@Test
public void endStreamTest()
{
// 返回Map
Stream.of("a", "b", "c").collect(Collectors.toMap(s -> s, s -> s));
// 返回 List
Stream.of("a", "b", "c").collect(Collectors.toList());
// 返回Set
Stream.of("a", "b", "c").collect(Collectors.toSet());
// ========================stream收集器 =============================//
/**
* @description:求数量
*/
// 写法1
Stream.of(1, 2, 3).count();
// 写法2
Stream.of(1, 2, 3).collect(Collectors.counting());
/**
* @description:求最值,最大值最小值都类似,比较方法有comparingDouble、comparingInt、comparingLong、甚至自定义
*/
// 写法1
Optional<Integer> res1 = Stream.of(1, 2, 3, 3).max((x, y) ->
{
return (x < y) ? -1 : ((x == y) ? 0 : 1);
});
System.out.println(res1.get());
// 写法2 依据数值流比较大小不需要参数
OptionalInt res2 = Stream.of(1, 2, 3, 3).mapToInt(a ->
{
return a;
}).max();
System.out.println(res2.getAsInt());
// 写法3 借助已有的Collectors.maxBy方法,没啥用,知道能这样写就好
Optional<Integer> res3 = Stream.of(1, 2, 3, 3).collect(Collectors.maxBy(Comparator.comparingInt(a ->
{
return a;
})));
System.out.println(res3.get());
/**
* @description:求和、求平均值 方法也很多,类似求最值
*/
// ========================stream连接字符串 =============================//
/**
* @description:连接字符串,默认中间无连接符,可以在joining方法中加入连接符 joining("_")
*/
Stream.of("a", "b").collect(Collectors.joining());
Stream.of("a", "b").reduce("", (a, b) ->
{
return a + b;
});
/**
* @description:自定义规约操作
* @param:1.初始值
* @param:2.对流中的数据进行处理
* @param:3.对处理后的元素进行自定义规约操作
*/
Stream.of("a", "b", "c").collect(Collectors.reducing("begin:", a ->
{
return a;
}, (a, b) ->
{
return a + b;
}));
// ========================stream连接字符串 =============================//
/**
* @description:将元素按指定规则分组
*/
Map<String, List<String>> group1 = Stream.of("a", "b", "c").collect(Collectors.groupingBy(a ->
{
if ("a".equals(a))
{
return "isA";
}
else if ("b".equals(a))
{
return "isB";
}
else
{
return "isOthers";
}
}));
// 可以在collect方法中添加参数,如再次分组或者统计每个分组的数量
Map<String, Long> group2 = Stream.of("a", "b", "c").collect(Collectors.groupingBy((a) ->
{
if ("a".equals(a))
{
return "isA";
}
else if ("b".equals(a))
{
return "isB";
}
else
{
return "isOthers";
}
}, Collectors.counting()));
}
结尾
本篇文章所有代码在本人github库里,[Java8StreamAPI.java]Java8StreamAPI.java,有兴趣的朋友可以看一下。
看到这么多代码,有人可能要问号警告了,相信我,按代码敲一遍,从此流操作就是so easy!
如果觉得介绍的海星,帮忙点个赞,可别下次一定。?
版权声明:本文为a936687045原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。