What is equivalent to C##39;s Select clause in JAVA#39;s streams API(什么相当于 JAVA 的流 API 中的 C# 的 Select 子句)
问题描述
我想过滤 Person 类的列表,最后使用 Streams 映射到 Java 中的某个匿名类.我可以在 C# 中非常轻松地做同样的事情.
I wanted to filter list of Person class and finally map to some anonymous class in Java using Streams. I am able to do the same thing very easily in C#.
人物类
class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
将结果映射为期望格式的代码.
Code to map the result in desire format.
List<Person> lst = new List<Person>();
lst.Add(new Person() { Name = "Pava", Address = "India", Id = 1 });
lst.Add(new Person() { Name = "tiwari", Address = "USA", Id = 2 });
var result = lst.Select(p => new { Address = p.Address, Name = p.Name }).ToList();
现在,如果我想访问任何新创建类型的属性,我可以使用下面提到的语法轻松访问.
Now if I wanted to access any property of newly created type I can easily access by using below mentioned syntax.
Console.WriteLine( result[0].Address);
理想情况下,我应该使用循环来遍历结果.
Ideally I should use loop to iterate over the result.
我知道在 java 中我们为 ToList 收集和为 Select 映射.但我无法只选择 Person 类的两个属性.我该怎么做Java
I know that in java we have collect for ToList and map for Select. But i am unable to select only two property of Person class. How can i do it Java
推荐答案
Java 没有结构类型.您可以将值映射到的最接近的是匿名类的实例.但也有明显的缺点.从 Java 16 开始,使用 record
会是更好的解决方案,即使它是命名类型并且可能稍微冗长一些.
Java does not have structural types. The closest you could map the values to, are instances of anonymous classes. But there are significant drawbacks. Starting with Java 16, using record
would be the better solution, even if it’s a named type and might be slightly more verbose.
例如假设
class Person {
int id;
String name, address;
public Person(String name, String address, int id) {
this.id = id;
this.name = name;
this.address = address;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
}
你可以的
List<Person> lst = List.of(
new Person("Pava", "India", 1), new Person("tiwari", "USA", 2));
var result = lst.stream()
.map(p -> {
record NameAndAddress(String name, String address){}
return new NameAndAddress(p.getName(), p.getAddress());
})
.collect(Collectors.toList());
result.forEach(x -> System.out.println(x.name() + " " + x.address()));
匿名内部类替代方案看起来像
The anonymous inner class alternative would look like
List<Person> lst = List.of(
new Person("Pava", "India", 1), new Person("tiwari", "USA", 2));
var result = lst.stream()
.map(p -> new Object(){ String address = p.getAddress(); String name = p.getName();})
.collect(Collectors.toList());
result.forEach(x -> System.out.println(x.name + " " + x.address));
但正如您可能注意到的那样,它仍然不如结构类型简洁.使用 var
声明 result
变量是引用我们无法通过名称引用的类型的唯一方法.这需要 Java 10 或更高版本,并且仅限于方法的范围.
but as you might note, it’s still not as concise as a structural type. Declaring the result
variable using var
is the only way to refer to the type we can not refer to by name. This requires Java 10 or newer and is limited to the method’s scope.
同样重要的是要记住,内部类可能会由于捕获对周围 this
的引用而造成内存泄漏.在示例中,每个对象还捕获用于其初始化的 p
的值.record
没有这些问题,而且它会自动获得合适的 equals
、hashCode
和 toString
实现,这意味着打印 System.out.println(result);
之类的列表或将其传输到 new HashSet<>(result)
之类的集合将产生有意义的结果.
It’s also important to keep in mind that inner classes can create memory leaks due to capturing a reference to the surrounding this
. In the example, each object also captures the value of p
used for its initialization. The record
doesn’t have these problems and further, it automatically gets suitable equals
, hashCode
, and toString
implementations, which implies that printing the list like System.out.println(result);
or transferring it to a set like new HashSet<>(result)
will have meaningful results.
此外,将 record
的声明移动到更广泛的范围要容易得多.
Also, it’s much easier to move the record
’s declaration to a broader scope.
在 Java 10 之前,lambda 表达式是唯一支持声明隐含类型变量的 Java 功能,该隐含类型可以是匿名的.例如,即使在 Java 8 中也可以使用以下内容:
Prior to Java 10, lambda expressions are the only Java feature that supports declaring variables of an implied type, which could be anonymous. E.g., the following would work even in Java 8:
List<String> result = lst.stream()
.map(p -> new Object(){ String address = p.getAddress(); String name = p.getName();})
.filter(anon -> anon.name.startsWith("ti"))
.map(anon -> anon.address)
.collect(Collectors.toList());
这篇关于什么相当于 JAVA 的流 API 中的 C# 的 Select 子句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:什么相当于 JAVA 的流 API 中的 C# 的 Select 子句
基础教程推荐
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01