自从有了Lambda,基本上就不会再写for循环,突然就有个想法,那以前没有Lambda的时候为什么每次操作集合的时候经常需要for循环呢?为什么就不封装一下呢?有了想法,那就想实现一下,参照Lambda的使用,写了一个过滤集合的实现,如下:
- class ListUtil {
- /** 从集合中过滤出满足指定条件的元素 */
- public static <T> List<T> filter(List<T> list, Condition<T> condition) {
- List<T> resultList = new ArrayList<>();
- for (T item : list) {
- if (condition.isWant(item)) {
- // 如果此item是我们想要的,就加入到结果列表中
- resultList.add(item);
- }
- }
- return resultList;
- }
- }
-
- /** 条件 */
- interface Condition<T> {
- /** 判断指定的item是否是我们想要的,如果是想要的就返回true,否则返回false */
- boolean isWant(T item);
- }
-
没错,就是这么简单,一个工具类方法filter,一个接口类Condition,有了这两个东西,以后需要从集合中过滤元素的时候就再也不用写循环了,只需调用filter函数,传入一个集合,再传入一个过滤条件即可,过滤条件的功能就是用于指定你想要过滤什么样的元素,比如:有一个Person的列表,我想要过获取列表中所有姓张的人,代码如下:
- public class Person {
- public String name;
- public int age;
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- @Override
- public String toString() {
- return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
- }
- }
-
- List<Person> personList = new ArrayList<>();
- personList.add(new Person("张三", 18));
- personList.add(new Person("李四", 23));
- personList.add(new Person("张小虎", 16));
- personList.add(new Person("王五", 28));
-
如上代码,这是一个Person类,没什么好说的,我们还创建了一个Person的集合。接下来我们想过滤出这个集合中所有姓张的人,代码如下:
- List<Person> resultList = ListUtil.filter(personList, new Condition<Person>() {
- @Override
- public boolean isWant(Person item) {
- return item.name.startsWith("张");
- }
- });
-
- System.out.println(resultList);
-
输出结果如下:
- [Person{name='张三', age=18}, Person{name='张小虎', age=16}]
-
OK,成功实现我们需要的功能。接下来,我想找出所有年龄大于20岁的人,也不需要再写for循环了,代码如下:
- List<Person> resultList = ListUtil.filter(personList, new Condition<Person>() {
- @Override
- public boolean isWant(Person item) {
- return item.age > 20;
- }
- });
-
- System.out.println(resultList);
-
输出结果如下:
- [Person{name='李四', age=23}, Person{name='王五', age=28}]
-
OK,完美!不论过滤什么,我们都不需要再写循环语句了,只是写起来麻烦了一点,每次要创建一个Predicate对象,其实我们真正需要的就是一个判断语句而已,如:item.age > 20,所以在jdk1.8的时候出来的函数式接口就非常好用了,使用函数式接口修改如上代码,如下:
- List<Person> resultList = ListUtil.filter(personList, item -> item.age > 20)
-
舒服!!当然,使用jdk1.8之后 我们就不需要自己去写filter函数,集合类中已经自带此函数。
有了这个经验,我们就可以实现更多的功能,比如从集合中查找满足指定条件的一个元素,代码如下:
- class ListUtil {
-
- /** 从集合中找出满足指定条件的第一个元素 */
- public static <T> T find(List<T> list, Condition<T> condition) {
- for (T item : list) {
- if (condition.isWant(item)) {
- // 如果此item是我们想要的,就返回
- return item;
- }
- }
- return null;
- }
- }
-
接下来,我们使用之前的personList集合,第一个年龄18岁的人,代码如下:
- Person person = ListUtil.find(personList, new Condition<Person>() {
- @Override
- public boolean isWant(Person item) {
- return item.age == 18;
- }
- });
-
- System.out.println(person);
-
输出如下:
- Person{name='张三', age=18}
-
所以在没有Lambda的年代,我们没有这种思想,就经常做很多重复工作,其实这个模式不就是经典的策略设计模式么?相同的逻辑只写一次,不同的逻辑交由接口完成。以后在开发的时候,如果发现好几个地方代码好多重复的,但是有有一小部分不太一样,这时候就要使用策略模式了(不一定是for循环的代码),把不同的部分抽取成接口,相同的代码只写一次。