JDK8 Stream 初识

点这里
Stream作为jdk8的一种重要特性,我们应该了解多一些。

为什么会有Stream?

在Stream出现之前,我们对集合中的元素进行一些操作需要先遍历每个元素再进行操作。如:

	  LinkedHashMap<String, Integer> linkedHashMap =  new LinkedHashMap<String, Integer>();
	  linkedHashMap.put("1", 1);
	  linkedHashMap.put("2", 2);
	  linkedHashMap.put("3", 3);
	  linkedHashMap.put("4", 4);
	  LinkedHashMap<String, Integer> linkedHashMap2 =  new LinkedHashMap<String, Integer>();	  
	  for (Entry entry : linkedHashMap.entrySet()) {
		  int v = (int)entry.getValue();
		linkedHashMap2.put((String)entry.getKey(), v*2);
	}
	//结果:
	//[1=1, 2=2, 3=3, 4=4]
	//[1=2, 2=4, 3=6, 4=8]

在1.8我们怎么实现呢?

HashMap<String, Integer> hashMap = (HashMap<String, Integer>) linkedHashMap
				.entrySet()
				.stream()
				.collect(
						Collectors.toMap(a -> a.getKey(), a -> a.getValue() * 2));
System.out.println(hashMap.entrySet());
//[1=2, 2=4, 3=6, 4=8]

当你熟练掌握stream用法时,对集合的操作就很方便简单了。

什么是Stream?

点这里
Stream 是用函数式编程方式在集合类上进行复杂操作的工具,其集成了Java 8中的众多新特性之一的聚合操作,开发者可以更容易地使用Lambda表达式,并且更方便地实现对集合的查找、遍历、过滤以及常见计算等。

集合讲的是数据,流讲的是计算

1> Stream 自己不会存储元素
2> Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream
3> Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行

Stream 的操作三个步骤
1> 创建 Stream : 一个数据源 (如 : 集合、数组), 获取一个流
2> 中间操作 : 一个中间操作链,对数据源的数据进行处理
3> 终止操作(终端操作) : 一个终止操作,执行中间操作链,并产生结果

创建流:

  1. collection中扩展了default 方法
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
collection.stream()
collection.parallelStream()
  1. Arrays 类中增加了 stream() 静态方法
    public static <T> Stream<T> stream(T[] array) {
        return stream(array, 0, array.length);
    }
	Stream<Integer> stream2 = Stream.of(1, 2, 3, 4, 5, 6);
	int [] a = {1,2,3};
	IntStream aStream= Arrays.stream(a);

还有几种创建方法我没有掌握,读者可以点击上面的连接查看。

Stream的操作

操作类型 接口方法
中间操作 concat() distinct() filter() flatMap() limit() map() peek()skip() sorted() parallel() sequential() unordered()
结束操作 allMatch() anyMatch() collect() count() findAny() findFirst() forEach() forEachOrdered() max() min() noneMatch() reduce() toArray()
  • 1 中间操作
方 法 描 述
切片
filter(Predicate p) 接收 Lambda , 从流中排除某些元素
distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
limit(long maxSize) 保留前n个
skip(long n) 去掉前n个
映射
map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
mapToDouble(ToDoubleFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream
mapToInt(ToIntFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream
mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream
flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
排序
sorted() 产生一个新流,其中按自然顺序排序
sorted(Comparator comp) 产生一个新流,其中按比较器顺序排序

我们来写一些例子加深印象,由于是中间方法所以在结尾加了foreach(终止方法)

//原数据
List<String> arrayList =Arrays.asList("1","2","3","3","4","5");
List<String> arrayList2 = Arrays.asList("a", "b", "c", "d", "e", "f");
  • 切片型

过滤filter

arrayList.stream().filter(e->e.equals("3")).forEach(System.out::println);
//3 3

删除重复distinct

arrayList.stream().distinct().forEach(System.out::println);
//1 2 3 4 5

筛选limit

arrayList.stream().limit(3).forEach(System.out::println);
//1 2 3

跳过skip

arrayList.stream().skip(4).forEach(System.out::println);
//4 5 
  • 映射型

map

arrayList.stream().map(e->e+"A").forEach(System.out::println);
//1A 2A 3A 3A 4A 5A

mapToInt/mapToDouble/mapToLong

arrayList.stream().mapToInt(e -> Integer.parseInt(e))
	.filter(e -> e==3).forEach(System.out::println);
//3 3

flatMap

Stream.of(arrayList, arrayList2).flatMap(u -> u.subList(0, 2).stream())
				.forEach(System.out::println);
//1 2 a b
  • 排序型

sorted

List<String> arrayList3 = Arrays.asList("9", "2", "3", "3", "4", "1");
arrayList3.stream().sorted().forEach(System.out::println);
// 1 2 3 3 4 9
arrayList3.stream().sorted((x, y) -> {
			return x.compareTo(y);
		}).forEach(System.out::println);
// 1 2 3 3 4 9

我好像对compareto,compareable,comparetor 是不是很懂,明天整理下

  • 2 终止操作
方 法 描 述
allMatch(Predicate p) 检查是否匹配所有元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配所有元素
findFirst() 返回第一个元素
findAny() 返回当前流中的任意元素
count() 返回流中元素总数
max(Comparator c) 返回流中最大值
min(Comparator c) 返回流中最小值
forEach(Consumer c) 内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反, Stream API 使用内部迭代)
归纳
reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回 T
reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回 Optional
收集
collect(Collector c) 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法

我们再来对终止操作进行举例:

reduce 将元素值结合起来

String sum =  arrayList.stream().reduce( "",(x,y)->(x+y) );
Optional<String> sum2 =  arrayList.stream().reduce((x,y)->(x+y) );
System.out.println( "Sum:  "+sum+"  Sum2:   "+ sum2 );
//Sum:  123345  Sum2:   Optional[123345]

anymatch/allmatch/nomatch

boolean flag = arrayList.stream().anyMatch(e->e.equals("1"));
System.err.println(flag);
// true

count

long num = arrayList.stream().count();
System.err.println("num: "+num+"  size: "+arrayList.size());

collection

		Map<String, List<String> > resultmap=arrayList.stream().collect(Collectors.groupingBy(e->{
			if ( e.equals("1") ) {
				return "ok";				
			}
			else {
				return e;
			}
			
		}));
						
		for (Entry entry : resultmap.entrySet()) {
			System.out.println(entry.getKey()+"   "+entry.getValue());
		}
		
//2   [2]
//3   [3, 3]
//4   [4]
//5   [5]
//ok   [1]

猜你喜欢

转载自blog.csdn.net/qq_31941773/article/details/83781630