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。

 

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