什么是 Stream
Jdk1.8 为了强化对集合的操作,新增了Stream 特性,使开发者对集合的操作更加简便,快速!Stream 是提供了 元素流上的功能样式操作的类
例如集合上的map-reduce转换。例如:
int sum = widgets.stream()
.filter(b -> b.getColor() == RED)
.mapToInt(b -> b.getWeight())
.sum();
Stream 的特性
流在几个方面与集合不同:
-
没有存储空间。流不是存储元素的数据结构。相反,它通过一系列计算操作从数据结构,数组,生成器功能或I / O通道等源中传递元素。
-
本质上是功能性的。对流的操作会产生结果,但不会修改其源。例如,对Stream 从集合中获取的a Stream进行过滤会产生一个不包含过滤后元素的新元素,而不是从源集合中删除元素。
-
懒惰寻求。许多流操作(例如过滤,映射或重复删除)可以延迟实施,从而暴露出进行优化的机会。
-
可能无界。尽管集合的大小是有限的,但流不是必需的。诸如limit(n)或 的短路操作findFirst()可以允许对无限流的计算在有限时间内完成。
-
消耗品。在流的生存期内,流的元素只能访问一次。与一样Iterator,必须生成新的流以重新访问源中的相同元素。
流可以通过多种方式获得。一些示例包括:
从Collection通过stream()与 parallelStream()方法;
从数组通过Arrays.stream(Object[]);
从上流类静态工厂方法,例如 Stream.of(Object[]), IntStream.range(int, int) 或Stream.iterate(Object, UnaryOperator);
文件的行可以从以下位置获得BufferedReader.lines():
可以从中的方法获得文件路径流Files。
可以从中获得随机数流Random.ints();
在JDK许多其他流的轴承的方法,包括 BitSet.stream(), Pattern.splitAsStream(java.lang.CharSequence),和JarFile.stream()。
Stream 相关用法案例:
/**
* 获取第一个值
* 如果 stream 没有顺序 那么都有可能返回
* 如果所选元素 为 空 那么 抛出 NullPointException
*/
public static void getFirstValue(){
List<Integer> list1 = getList();
Optional<Integer> first = list1.stream().findFirst();
System.out.println(first);
}
/**
* 去重复
*/
public static void distinctTest(){
List<Integer> list = getList();
List<Integer> list1 = list.stream().distinct().collect(toList());
System.out.println(list1);
}
/**
* 获取任意 元素
* 如果流为空,则为空
*/
public static void findAnyTest(){
List<Integer> list1 = getList();
Optional<Integer> any = list1.stream().findAny();
System.out.println(any);
}
/**
* 过滤器
*/
public static void filterTest(){
List<Integer> list1 = getList();
List list = list1.stream().filter(str->{
if(1 == str||2 == str){
return true;
}
return false;
}).collect(toList());
System.out.println(list);
}
/**
* 元素加工处理
*
*/
public static void mapTest(){
List<Integer> list1 = getList();
List<Integer> collect = list1.stream().map(str -> str + 1).collect(toList());
System.out.println(collect);
}
/**
* 相对 Map 更深层次
*/
public static void flatMapTest(){
List<Person> personList = getPeopleList();
// 深层次的循环
// flatMap可以操作对象里面的对象,而map只能操作第一层。
// 如果入参的是对象,那么 flatMap 可以操作到对象的属性,而map 只能操作到 对象
// 及早求值
List resultList1 = personList.stream()
.flatMap(person -> Arrays.stream(person.getName().split(" "))).collect(toList());
//打印姓名
System.out.println(resultList1);
// 对比 map 惰性求值
List<Stream<String>> resultList2 = personList.stream()
.map(person -> Arrays.stream(person.getName().split(" "))).collect(toList());
// 打印 Stream 对象 地址
System.out.println(resultList2);
}
/**
* 累加测试
*/
public static void reduceTest(){
List<Integer> arr = getList();
// 累加
Integer reduce1 = arr.stream().reduce(10, (sun, item) -> {
return sun + item;
});
//简写
Integer reduce2 = arr.stream().reduce(10, (sun, item) ->sun + item);
// 字符串累加 拼接
String reduce3 = Stream.of("1", "2", "3")
.reduce("0", (x, y) -> (x + "," + y));
System.out.println(reduce2);
// 打印 17
System.out.println(reduce1);
System.out.println(reduce2);
System.out.println(reduce3);
}
/**
* 以下演示 Collect 的相关用法
*
* 1 toList()
*
* 2、toSet()
*
* 3、toMap()
*
* 4、自定义
*/
public static void toListTest(){
List<Double> collect = getList().stream().map(Integer::doubleValue).collect(toList());
//打印 [1.0, 3.0, 1.0, 2.0]
System.out.println(collect);
}
public static void toSetTest(){
Set<Double> collect = getList().stream().map(Integer::doubleValue).collect(toSet());
//打印 [1.0, 2.0, 3.0] 自动去重复
System.out.println(collect);
}
public static void toMapTest(){
List<Person> personList = getPeopleList();
Map<String, Integer> collect = personList.stream().collect(toMap(Person::getName, Person::getAge));
//打印 {zhang2=3, zhang3=4, zhang0=1, zhang1=2, zhang8=9, zhang9=10, zhang6=7, zhang7=8, zhang4=5, zhang5=6} 乱序
System.out.println(collect);
}
/**
* 转换成 指定类型
*/
public static void toTreeSetTest(){
List<Integer> list = getList();
TreeSet collect = list.stream()
.collect(Collectors.toCollection(TreeSet::new));
System.out.println(collect);
}
/**
* 分组
*/
public static void toGroupTest(){
List<Person> data = getPeopleList();
Map<Boolean, List<Person>> collect = data.stream()
.collect(Collectors.groupingBy(person -> person.getAge()>5));
Iterator<Map.Entry<Boolean, List<Person>>> iterator = collect.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<Boolean, List<Person>> next = iterator.next();
List<Person> personList = next.getValue();
if(next.getKey() == true){
personList.forEach(person->System.out.println(Strings.lenientFormat("年龄 5岁以上的-姓名: %s",person.getName())));
}else{
personList.forEach(person->System.out.println(Strings.lenientFormat("年龄 5岁以下的-姓名: %s",person.getName())));
}
}
}
/**
* 分隔
*/
public static void toJoiningTest(){
List<Person> peopleList = getPeopleList();
String collect = peopleList.stream()
.map(person -> person.getName())
//以 , 分割 前后缀分别为 { }
.collect(Collectors.joining(",", "{", "}"));
System.out.println(collect);
}
/**
* 累加
*/
public static void toReduceTest(){
List collect = Stream.of("1", "2", "3","4").collect(
Collectors.reducing(new ArrayList(), x -> Arrays.asList(x), (y, z) -> {
y.addAll(z);
return y;
}));
System.out.println(collect);
}
/**
* 并发
*/
public static void paralleList(){
int size = 10;
List<Integer> list = new ArrayList<>(size);
for (Integer i = 0; i < size; i++) {
list.add(new Integer(i));
}
List<Integer> temp1 = new ArrayList<>(size);
//老的
long start=System.currentTimeMillis();
for (Integer i: list) {
temp1.add(i);
}
System.out.println(+System.currentTimeMillis()-start);
//同步
long start1=System.currentTimeMillis();
list.stream().collect(Collectors.toList());
System.out.println(System.currentTimeMillis()-start1);
//并发
long start2=System.currentTimeMillis();
list.parallelStream().collect(Collectors.toList());
System.out.println(System.currentTimeMillis()-start2);
}
/**
* 线程安全问题
线程不安全问题,
1.可以使用 Lock,Synchronize等锁机制 使线程安全
2.使用线程安全的集合类 如 CopyOnWriteArrayList,ConcurrentHashMap
*/
public static void paralleSafety(){
List<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<Integer>();
List<Integer> list3 = new ArrayList<Integer>();
List<Integer> list4 = new CopyOnWriteArrayList<Integer>();
long millis = System.currentTimeMillis();
IntStream.range(0,1000).forEach(list1::add);
long endMillis = System.currentTimeMillis();
// System.out.println(endMillis-millis);
//线程不安全
// IntStream.range(0,1000).parallel().forEach(list2::add);
IntStream.range(0,1000).parallel().forEach(list4::add);
long millis1 = System.currentTimeMillis();
Lock lock = new ReentrantLock();
IntStream.range(0, 1000).parallel().forEach(i -> {
lock.lock();
try {
list3.add(i);
}finally {
lock.unlock();
}
});
long endMillis1 = System.currentTimeMillis();
// System.out.println(endMillis1-millis1);
System.out.println(list1.size());
System.out.println(list2.size());
System.out.println(list3.size());
System.out.println(list4.size());
}
/**
* 调试
* .
* 使用 peek 打印值
*/
public static void debugTest(){
List<Integer> list = getList();
List<Long> collect = list.stream().map(value -> value.longValue()).peek(v -> {
System.out.println(v == 10);
}).collect(toList());
System.out.println(collect);
}
评论区