假设我有一个 Person 类,其中包含 FirstName、LastName、Age、Salary 等字段。现在我在 C# linq 中编写了这段代码,其中 Person 是一个列表。
var lstFirstAndLastNamesOnly = persons.Where(x => x.Age > 35).Select(x => new {x.FirstName, x.LastName}).ToList();
Run Code Online (Sandbox Code Playgroud)
这将为我提供一个具有名字和姓氏的匿名类型。我如何在 Java 8 中编写这样的东西?当我在类中有 100 个字段时,只返回少数字段,有什么更好的方法呢?
Hol*_*ger 11
嗯,Java 编程语言具有匿名类型,但它们不像 C# 示例中那样有用。即,以下内容可行:
\npersons.stream().filter(x -> x.age > 35)\n .map(x -> new Object(){ String first = x.firstName, last = x.lastName; })\n .forEach(name -> System.out.println(name.first + " " + name.last));\nRun Code Online (Sandbox Code Playgroud)\n您将注意到,匿名类型的声明仍然需要类型规范,该类型规范将是匿名类型的超类型。此外,您必须正式声明保存数据的成员的类型和名称。
\n在 JDK\xc2\xa010 之前,lambda 表达式是唯一可以声明变量(参数)而无需指定其类型并让编译器推断它的地方。
\n从 JDK\xc2\xa010 开始,您可以使用var关键字声明一个局部变量,其类型是从其初始值设定项推断出来的,即使它是不可表示的类型。
persons.stream().filter(x -> x.age > 35)\n .map(x -> new Object(){ String first = x.firstName, last = x.lastName; })\n .forEach(name -> System.out.println(name.first + " " + name.last));\nRun Code Online (Sandbox Code Playgroud)\n您可以在流畅的上下文中访问它,无需变量,这也适用于 JDK\xc2\xa010 之前的版本,例如
\nSystem.out.println(\n persons.stream().filter(x -> x.age > 35)\n .map(x -> new Object(){ String a = x.firstName, b = x.lastName; })\n .findFirst().get().a\n);\nRun Code Online (Sandbox Code Playgroud)\n但由于这只允许访问单个成员,所以它\xe2\x80\x99没什么用,因为,如果你只需要一个成员,你可以map访问成员值。
在此特定示例中,您可以使用两个元素String数组:
List<String[]> lstFirstAndLastNamesOnly = persons.stream()\n .filter(x -> x.age > 35)\n .map(x -> new String[] { x.firstName, x.lastName })\n .collect(Collectors.toList());\nlstFirstAndLastNamesOnly\n .forEach(name -> System.out.println(name[0]+" "+name[1]));\nRun Code Online (Sandbox Code Playgroud)\n但是,当然,它们不能替代真正的元组,特别是当您具有异构类型的元素时。
\n应当注意,这样的匿名类型仍然是不同的类型,即在不同代码位置创建的具有相同属性的另一个匿名类型仍然是不同的类型。事实上,即使具有相同属性值的实例也不相等,只要你不\xe2\x80\x99t添加适当的equals方法。
从 JDK\xc2\xa016 开始,您可以使用 arecord来实现此目的。它\xe2\x80\x99 不是一个匿名类,而是用于创建包含某些属性的临时类型的最佳工具。它\xe2\x80\x99s仍然是一个不同的类型,但它可以在本地声明\xc2\xb9并自动变得有用equals, hashCode, 和toString实现。
var name = persons.stream().filter(x -> x.age > 35)\n .map(x -> new Object(){ String first = x.firstName, last = x.lastName; })\n .orElse(null);\nif(name != null) System.out.println(name.first + " " + name.last);\nRun Code Online (Sandbox Code Playgroud)\n请注意,这再次用于var变量声明,因为Name映射函数内声明的记录不在范围内。同样,传递给的 lambda 表达式forEach推断出正确的元素类型。由于这依赖于局部变量的一项功能,因此仅当整个代码位于一个方法内时它才有效。
\xc2\xb9 甚至比匿名类更好,因为recordwon\xe2\x80\x99tthis从周围上下文捕获引用
| 归档时间: |
|
| 查看次数: |
4162 次 |
| 最近记录: |