什么相当于JAVA的流API中的C#的Select子句

Pav*_*ari 7 c# java java-8 java-stream

我想过滤Person类的列表,最后使用Streams映射到Java中的一些匿名类.我能够在C#中轻松地做同样的事情.

人类

class Person
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Address { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

用于以期望格式映射结果的代码.

 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();
Run Code Online (Sandbox Code Playgroud)

现在,如果我想访问新创建的类型的任何属性,我可以使用下面提到的语法轻松访问.

Console.WriteLine( result[0].Address);
Run Code Online (Sandbox Code Playgroud)

理想情况下,我应该使用循环来迭代结果.

我知道在java中我们收集了ToList并映射了Select.但我无法只选择Person类的两个属性.我怎么做Java

Hol*_*ger 13

好吧,您可以将Person实例映射到匿名类的实例,例如假设

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以做

List<Person> lst = Arrays.asList(
                       new Person("Pava", "India", 1), new Person("tiwari", "USA", 2));
List<?> result = lst.stream()
    .map(p -> new Object() { String address = p.getAddress(); String name = p.getName(); })
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

但是你可能会注意到,它并不简洁,而且更重要的是,result变量的声明不能引用匿名类型,这使得匿名类型的实例几乎无法使用.

目前,lambda表达式是唯一支持声明隐含类型变量的Java功能,它可以是匿名的.例如,以下内容可行:

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());
Run Code Online (Sandbox Code Playgroud)

  • @Federico Peralta Schaffner:这些是同一方法(或代码块)中的lambda表达式,因此它们总是被编译在一起,编译器可以在此时推断出"Stream <匿名类型在Java中不可表达".它类似于`new BaseClass(){void member(){}} .member()`,它早在Java 8之前工作.通常,匿名类型可以像任何其他类型一样使用,只要你在没有引用它们的情况下就可以使用它们.名称. (2认同)
  • @MalteHartwig eclipse编译器!= javac.它对我来说也不适用于eclipse (2认同)
  • @Holger我想知道如果我把它放在我们的代码库中,人们会怎么说:).绝对神奇的顺便说一句!不知道这是可能的 (2认同)

Tho*_*mas 0

如果您想创建新 实例的列表,Person您首先应该提供一个构造函数,例如如下所示:

class Person {
  public int id;
  public String name;
  public String address;

  public Person( int pId, String pName, String pAddress ) {
    super();
    id = pId;
    name = pName;
    address = pAddress;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用流:

List<Person> lst = new ArrayList<>();

lst.add(new Person(1, "Pava", "India" ));
lst.add(new Person( 2, "tiwari", "USA" ) );

//since id is an int we can't use null and thus I used -1 here    
List<Person> result = lst.stream().map(p -> new Person(-1, p.name, p.address)).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

如果您想过滤人员,只需filter()stream()和之间添加一个map()

List<Person> result = lst.stream().filter(p -> p.name.startsWith( "P" )).map(p -> new Person( -1, p.name, p.address )).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)