Java中如何复用循环逻辑遍历Dog、Cat两类列表实现独立打印
重复循环逻辑优化方案
这类重复代码的核心问题是把遍历执行、筛选规则、输出逻辑三个独立逻辑耦合在了每个分支里,只要把公共的遍历逻辑抽离,把可变的筛选、输出逻辑作为参数传入,就能彻底消除重复的循环代码,后续扩展也更方便。
方案1:利用多态做抽象(推荐,适合可修改实体类的场景)
先给Dog、Cat抽公共的行为接口,统一两类实体的公共方法:
public interface Animal { // 统一获取领养状态的方法 String getStatus(); // 每个动物自己实现自己的信息打印逻辑 void printInfo(); }
让Dog、Cat类都实现这个接口,把各自的打印逻辑写在自己的printInfo()方法里,不用把输出规则堆在公共打印方法中。
之后抽离唯一的一份通用遍历方法,把筛选规则作为可传参数:
// 通用遍历打印工具方法 private static void printAnimalList(List<? extends Animal> animalList, Predicate<Animal> filter) { for (Animal animal : animalList) { // 无过滤条件 或 满足过滤规则时执行打印 if (filter == null || filter.test(animal)) { animal.printInfo(); } } }
最后改造原来的分支逻辑,去掉所有重复的for循环:
public static void printAnimals(String listType) { switch (listType) { case "dog": printAnimalList(dogList, null); break; case "cat": printAnimalList(catList, null); break; case "available": Predicate<Animal> unreservedFilter = animal -> "unreserved".equals(animal.getStatus()); printAnimalList(dogList, unreservedFilter); printAnimalList(catList, unreservedFilter); break; default: throw new IllegalArgumentException("不支持的列表类型:" + listType); } }
这个方案的优势:
- 遍历逻辑全局只保留一份,后续修改遍历规则(比如加序号打印、统一异常捕获)只需要改一个地方
- 每个实体类自己管自己的打印逻辑,符合单一职责,修改单个动物的输出格式不需要动公共遍历代码
- 筛选逻辑可插拔,后续新增其他筛选规则(比如打印3岁以下的宠物、打印特定品种的宠物)只需要传入新的Predicate即可,不需要改动核心遍历逻辑
- 后续新增动物类型(比如兔子、仓鼠)时,只要实现
Animal接口,在分支里加一行调用即可,不需要重复写任何遍历逻辑
方案2:泛型通用方法(适合无法修改原有实体类的场景)
如果Dog、Cat是第三方依赖的类,没法直接修改源码让它们实现接口,可以用泛型+函数式参数的方式抽离遍历逻辑,完全不侵入原有代码:
/** * 通用列表遍历打印方法 * @param list 待遍历的任意类型列表 * @param filter 元素筛选规则,传null表示不筛选 * @param printer 元素的打印逻辑 */ private static <T> void printGenericList(List<T> list, Predicate<T> filter, Consumer<T> printer) { for (T item : list) { if (filter == null || filter.test(item)) { printer.accept(item); } } }
调用时按需传入筛选和打印规则即可,比如打印可领养动物的分支可以写成:
case "available": // 打印未预定的狗 printGenericList(dogList, dog -> "unreserved".equals(dog.getStatus()), dog -> System.out.println("unreserved dogs: " + dog) ); // 打印未预定的猫 printGenericList(catList, cat -> "unreserved".equals(cat.getStatus()), cat -> System.out.println("unreserved cats: " + cat) ); break;
这种写法灵活度极高,不管后续要加什么类型的列表、什么筛选规则、什么输出格式,都不用再重复写for循环结构。
额外注意
原代码中字符串比较的写法存在空指针风险,所有listType.equals("xxx")都建议改成"xxx".equals(listType),或者用Objects.equals(listType, "xxx"),避免入参为null时直接抛出异常。
内容的提问来源于stack exchange,提问作者user18942073
相关产品推荐
相关产品推荐

