lambda表達式(二)集合操作

目錄

案列一、數組

排序:

數組批量設值:

案例二、集合操作(List)

初始化一個集合

過濾

排序:

Map映射:

Match匹配:

Count計數:

Reduce約束:

方案一:使用collect方法

方案二:

方案三:變成數組

方案四:使用forEach

案例三、集合操作(Map)


案列一、數組

排序:

String[] arrays = new String[]{"king","queen","012","120","我們","你愁啥"};
Arrays.parallelSort(arrays,(o1,o2)->o1.length()-o2.length());
Arrays.parallelSort(arrays,new Comparator<String>(){
	@Override
	public int compare(String o1, String o2){
		//按字符串長度升序排列
		return o1.length()-o2.length();
	}
});
System.out.println(Arrays.toString(arrays));

輸出結果:[我們, 012, 120, 你愁啥, king, queen]

上面兩個一個是lambda表達式,一個是匿名接口寫法。如果不知道Comparator裏的compare方法壓根不知道怎麼寫lambda中表達方式。

類似斐波那契數列計算方式:

int[] arrays01 = new int[]{3,4,5,-3};
/**
 * 3
 * 3*4 = 12;
 * 12*5 = 60;
 * 60*(-3) = -180;
 * 和斐波那契數列的計算方式一樣
 */
Arrays.parallelPrefix(arrays01,(left,right)->left*right);
System.out.println(Arrays.toString(arrays01));

輸出結果: [3, 12, 60, -180]

數組批量設值:

long[] arrays02 = new long[5];
Arrays.parallelSetAll(arrays02, operand->operand*5);
System.out.println(Arrays.toString(arrays02));

輸出結果: [0, 5, 10, 15, 20]

案例二、集合操作(List)

初始化一個集合

List<String> sList = new ArrayList<String>();
sList.add("ddd2");  
sList.add("aaa2");  
sList.add("bbb1");  
sList.add("aaa1");  
sList.add("bbb3");  
sList.add("ccc");  
sList.add("bbb2");  
sList.add("ddd1");

過濾

sList.stream().filter((s)->s.startsWith("a"))
		.forEach(System.out::println);;

sList.stream().filter(new Predicate<String>(){
	@Override
	public boolean test(String s){
		return s.startsWith("a");
	}
}).forEach(s->System.out.println(s));

輸出 aa2,aa1

排序:

sList.stream().sorted((o1,o2)->(o1.length()-o2.length()))
	forEach(System.out::println);

Map映射:

中間操作map會將元素根據指定的Function接口來依次將元素轉成另外的對象,下面的示例展示了將字符串轉換爲大寫字符串。

sList.stream().map(String::toUpperCase).forEach(System.out::println);

sList.stream().map((s)->s.toUpperCase()).forEach(System.out::println);

sList.stream().map(new Function<String,String>() {

	@Override
	public String apply(String t) {
		return t.toUpperCase();
	}
}).forEach(System.out::println);

Match匹配:

boolean anyStartWithA = sList.stream() .anyMatch((s)->s.startsWith(“a”));//true

集合中存在一個字符串以“a”開頭。

boolean allStartsWithA = sList.stream()
        .allMatch((s)->s.startsWith("a"));//false

集合中所有字符串都以“a”開頭。

boolean noneStartsWithZ = sList.stream()
         .noneMatch((s)->s.startsWith("z"));//true

集合中所有字符串都不是以“z”開頭。

Count計數:

計數是一個最終操作,返回Stream中元素的個數,返回值類型是long。

long startWithB = sList.stream()
	.filter((s)->s.startsWith("b")).count();//3

Reduce約束:

這是一個最終操作,允許通過指定的函數來講stream中的多個元素規約爲一個元素,規越後的結果是通過Optional接口表示的。

Optional<String> reduced = sList.stream().reduce((s1,s2)->s1+"#"+s2);
reduced.ifPresent(System.out::println);

輸出結果: ddd2#aaa2#bbb1#aaa1#bbb3#ccc#bbb2#ddd1

ifPresent是如果reduced中有值就輸出,沒有就不輸出。

下面代碼就不會有任何輸出,將所有數據都過濾了,

Optional<String> reduced = sList.stream()
	.filter((s)->s.startsWith("z"))
	.reduce((s1,s2)->s1+"#"+s2);

OK,集合操作就暫時到這裏,上述所有都是串行Stream操作。

串行Stream上的操作是在一個線程中依次完成,而並行Stream則是在多個線程上同時執行。

下面看並行Stream,

以排序爲列,當然這是個錯誤的例子,排序時用這種並行很危險。

sList.parallelStream().sorted((o1,o2)->(o1.length()-o2.length()))
		.forEach(System.out::println);

將List的stream()改爲parallelStream()就是並行排序,但是可以運行比較一下和stream()排序出來的結果,上面代碼並行排序並不能真正的排序,可以理解爲多個線程排序,每個線程排序幾個數據,導致彙總的時候整體就雜亂了。

但也有優點就是快。

下面還有一點需要考慮的地方,如何將一個從集合轉變爲Stream對象再變爲集合,也就是說如何將filter後重新在變爲一個集合?

方案一:使用collect方法

Stream<String> stream = sList.stream()
		.sorted((o1,o2)->(o1.length()-o2.length()));
sList = stream.collect(Collectors.toList());
sList.forEach(System.out::println);

方案二:

sList = stream.collect(Collectors.toCollection(ArrayList::new));

方案三:變成數組

String[] strs = stream.toArray(String[]::new);

方案四:使用forEach

List<String> newList = new ArrayList<String>();
sList.forEach(newList::add);

案例三、集合操作(Map)

首先聲明一點Map類型不支持stream,但其中依舊有一些可以用到lambda表達式的地方。

初始化一個Map:

Map<String,String> map = new HashMap<String,String>();
for(int i=0;i<10;i++){
	/**
	 * If the specified key is not already associated with a value
	 *  (or is mapped to null) associates it with the given value
         *   and returns null,
	 *   else returns the current value.
	 */
	map.putIfAbsent("key"+i, "val"+i);
}
//遍歷輸出map的Key和Value
map.forEach((key,val)->System.out.print(key+":"+val+"  "));

發現map中有一個好玩的方法putIfAbsent,如同它的英文解釋,如果這個key已經在map中設置過了那麼此方法就返回當前值,如果沒有設置那麼就爲這個key設置value,同時返回null。

還有就是循環輸出Map中key和value的時候,終於不需要寫好幾行代碼的Iterator了。

上述輸出爲: key1:val1 key2:val2 key0:val0 key5:val5 key6:val6 key3:val3 key4:val4 key9:val9 key7:val7 key8:val8

map.computeIfPresent("key3",(key,val)->val+key);
System.out.println(map.get("key3"));//val3key3

此處是爲key3這個key設置值。如果存在就設置值,如果不存在這個key3就算了。它和computeIfAbsent不一樣。

map.computeIfAbsent("key23", key->"val"+key);

System.out.println(map.get("key23"));//valkey23

原本初始化沒有key23這個key,但是此方法是如果缺失key23這個key,那麼就設置到Map中。

map.getOrDefault("key93", "not found")

上面這段代碼返回map中的value,但是key93沒有,所以返回not found,如果換成key23,那麼就返回key23的value——valkey23

map.merge("key3", "concat", (value,newValue)->value.concat(newValue));

System.out.println(map.get("key3"));

Merge做的事情是如果鍵名不存在則插入,否則則對原鍵對應的值做合併操作並重新插入到map中。和computeIfAbsent()方法很像。

所以上面輸出val3concat,如果沒有key3這個鍵存在,那麼就是設置值,輸出concat。

 

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