使用 lambdaj 在没有循环的情况下操作集合






4.50/5 (5投票s)
一个线程安全的静态方法库,提供内部 DSL,可以在没有循环的情况下操作 Java 集合。
引言
你有没有读过或写过相同的两三行代码,它们经常一起出现,即使它们操作的是不同的对象,但感觉像是一回事?而且这些重复通常涉及某种集合迭代或更普遍的操作?当开发者找到有趣的部分时,他们最终会学会过滤掉并忽略这些代码中的重复。但即使开发者习惯了,也会减慢他们的速度。这样的代码显然是为计算机执行而编写的,而不是为开发者阅读而编写的。
lambdaj是一个库,通过允许以伪函数式和静态类型的方式操作集合,使解决这个问题更容易。根据我们的经验,迭代集合,尤其是在嵌套循环中,通常容易出错并使代码的可读性降低。这个库的目的是通过使用一些函数式编程技术来缓解这些问题,但又不失Java的静态类型。我们施加了这个最后的约束,以使重构更容易、更安全,并允许编译器完成其工作。
在没有显式循环的情况下访问集合
lambdaj的主要目的是部分消除编写(通常是嵌套且可读性差的)循环的负担,同时迭代集合。特别是,它允许迭代集合以
- 根据给定的条件过滤其项目
- 使用给定的规则转换每个项目
- 从每个项目中提取给定的属性
- 根据其某个属性的值对项目进行排序
- 根据一个或多个属性的值对项目进行分组或索引
- 在每个项目上调用一个方法
- 对项目或其某个属性的值求和(或更普遍地聚合)
- 连接项目或其某个属性的值的
string
表示
而无需编写任何显式循环。
lambdaj是如何工作的?
lambdaj的基础是两个想法。第一个是将对象集合视为单个对象,允许将单个方法调用传播到集合中的所有对象,如下例所示
List<Person> personInFamily = asList(new Person("Domenico"),
new Person("Mario"), new Person("Irma"));
forEach(personInFamily).setLastName("Fusco");
在这个例子中,列表中的所有人都属于同一个家庭,所以他们都有相同的姓氏。forEach
方法实际上返回一个代理对象,该对象既实现了Iterable接口,也实现了给定列表中每个对象中的所有方法。这允许在forEach
方法返回的对象上调用Person
对象的方法,就像它是Person
类的一个实例一样。当你这样做时,在底层,lambdaj会将你的调用传播到集合中的所有对象。
lambdaj构建的第二个想法是通过使用lambdaj的on构造,以静态类型的方式拥有指向Java方法的指针的可能性。这允许轻松安全地定义给定lambdaj特性必须应用于哪个参数。例如,在以下语句中,我们使用on
构造来说明必须对列表中的人员进行排序的参数(他们各自的年龄)
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());
将最后一条语句与在纯Java中实现相同结果所需的代码段进行比较
List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
}
});
很明显,lambdaj如何提高编写代码的效率,并且可能更重要的是,当您被要求维护它时,它的可读性。
lambdaj特性
如前所述,lambdaj旨在轻松地操作集合。它的特性旨在过滤、转换、索引和聚合集合的项目,而无需显式地对其进行迭代。此外,lambdaj API 被设计成可以轻松地连接,以便在单个语句中联合使用两个或多个特性。要更详细地研究这些特性,并可能下载并开始使用 lambdaj,请在此处查看 here。
历史
- 2009 年 6 月 14 日:初次发布