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]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章