Lambda表达式你会用吗? (3)

Java7及以前我们可以用增强的for循环实现:

// 使用曾强for循环迭代 ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too")); for(String str : list){ if(str.length()>3) System.out.println(str); }

现在使用forEach()方法结合匿名内部类,可以这样实现:

// 使用forEach()结合匿名内部类迭代 ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too")); list.forEach(new Consumer<String>(){ @Override public void accept(String str){ if(str.length()>3) System.out.println(str); } });

上述代码调用forEach()方法,并使用匿名内部类实现Comsumer接口。到目前为止我们没看到这种设计有什么好处,但是不要忘记Lambda表达式,使用Lambda表达式实现如下:

// 使用forEach()结合Lambda表达式迭代 ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too")); list.forEach( str -> { if(str.length()>3) System.out.println(str); });

上述代码给forEach()方法传入一个Lambda表达式,我们不需要知道accept()方法,也不需要知道Consumer接口,类型推导帮我们做了一切。

removeIf()

该方法签名为boolean removeIf(Predicate<? super E> filter),作用是删除容器中所有满足filter指定条件的元素,其中Predicate是一个函数接口,里面只有一个待实现方法boolean test(T t),同样的这个方法的名字根本不重要,因为用的时候不需要书写这个名字。

需求:假设有一个字符串列表,需要删除其中所有长度大于3的字符串。

我们知道如果需要在迭代过程冲对容器进行删除操作必须使用迭代器,否则会抛出ConcurrentModificationException,所以上述任务传统的写法是:

// 使用迭代器删除列表元素 ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too")); Iterator<String> it = list.iterator(); while(it.hasNext()){ if(it.next().length()>3) // 删除长度大于3的元素 it.remove(); }

现在使用removeIf()方法结合匿名内部类,我们可是这样实现:

// 使用removeIf()结合匿名名内部类实现 ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too")); list.removeIf(new Predicate<String>(){ // 删除长度大于3的元素 @Override public boolean test(String str){ return str.length()>3; } });

上述代码使用removeIf()方法,并使用匿名内部类实现Precicate接口。相信你已经想到用Lambda表达式该怎么写了:

// 使用removeIf()结合Lambda表达式实现 ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too")); list.removeIf(str -> str.length()>3); // 删除长度大于3的元素

使用Lambda表达式不需要记忆Predicate接口名,也不需要记忆test()方法名,只需要知道此处需要一个返回布尔类型的Lambda表达式就行了。

replaceAll()

该方法签名为void replaceAll(UnaryOperator<E> operator),作用是对每个元素执行operator指定的操作,并用操作结果来替换原来的元素。其中UnaryOperator是一个函数接口,里面只有一个待实现函数T apply(T t)。

需求:假设有一个字符串列表,将其中所有长度大于3的元素转换成大写,其余元素不变。

Java7及之前似乎没有优雅的办法:

// 使用下标实现元素替换 ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too")); for(int i=0; i<list.size(); i++){ String str = list.get(i); if(str.length()>3) list.set(i, str.toUpperCase()); }

使用replaceAll()方法结合匿名内部类可以实现如下:

// 使用匿名内部类实现 ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too")); list.replaceAll(new UnaryOperator<String>(){ @Override public String apply(String str){ if(str.length()>3) return str.toUpperCase(); return str; } });

上述代码调用replaceAll()方法,并使用匿名内部类实现UnaryOperator接口。我们知道可以用更为简洁的Lambda表达式实现:

// 使用Lambda表达式实现 ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too")); list.replaceAll(str -> { if(str.length()>3) return str.toUpperCase(); return str; }); sort()

该方法定义在List接口中,方法签名为void sort(Comparator<? super E> c),该方法根据c指定的比较规则对容器元素进行排序。Comparator接口我们并不陌生,其中有一个方法int compare(T o1, T o2)需要实现,显然该接口是个函数接口。

需求:假设有一个字符串列表,按照字符串长度增序对元素排序。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzgwpp.html