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

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

人类

class Person { public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } } 

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

  List lst = new List(); 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(); 

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

 Console.WriteLine( result[0].Address); 

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

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

好吧,你可以将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; } } 

你可以做

 List 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()); 

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

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

 List 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()); 

您似乎想要将具有3个属性的Person transform为具有2个属性的Holder。 这是一个简单的map操作:

 lst.stream().map(p -> new AbstractMap.SimpleEntry(p.address, p.name)) .collect(Collectors.toList()); 

SimpleEntry您的条目收集到SimpleEntry ,它只是两个值的持有者。 如果你需要两个以上,那你就不走运了 – 你需要创建自己的持有人(class级)。

如果您知道要选择哪些属性并且这不会改变,我建议您使用Person的属性子集编写一个小类。 然后,您可以将每个人映射到该类的实例并将其收集到列表中:

 Stream.of(new Person(1, "a", "aa"), new Person(2, "b", "bb"), new Person(3, "b", "bbb"), new Person(4, "c", "aa"), new Person(5, "b", "bbb")) .filter(person -> true) // your filter criteria goes here .map(person -> new PersonSelect(person.getName(), person.getAddress())) .collect(Collectors.toList()); // result in list of PersonSelects with your name and address 

如果所需属性集的变化,则可以使用数组。 它看起来与您的C#代码更相似,但不提供类型安全性:

 Stream.of(new Person(1, "a", "aa"), new Person(2, "b", "bb"), new Person(3, "b", "bbb"), new Person(4, "c", "aa"), new Person(5, "b", "bbb")) .filter(person -> true) .map(person -> new Object[] {person.getName(), person.getAddress()}) .collect(Collectors.toList()) .forEach(p -> System.out.println(Arrays.asList(p))); // output: [a, aa], [b, bb], [b, bbb], [c, aa], [b, bbb] 

如果要创建新的 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; } } 

然后你可以使用流:

 List 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 result = lst.stream().map(p -> new Person(-1, p.name, p.address)).collect(Collectors.toList()); 

如果你想过滤人,那么只需在stream()map()之间放一个filter() map()

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