Eli*_*nes 6 java lambda list filter java-stream
我有 2 个包含多个对象的列表。我想过滤在特定属性处包含相同字符串值的对象。因此,假设listA包含具有属性的对象id。与 相同listB,尽管它包含不同的对象。不过,两个列表中的某些对象具有相同的 id。我想过滤这些对象并将它们放入新列表中。这是我到目前为止得到的:
List<Customer> Clist = Customer.getAllCustomers();
List<License> Llist = License.getAllLicenses();
Predicate<Customer> customerNotNullPredicate = u -> (u.id != null);
Predicate<License> licenseNotNullPredicate = u -> (u.id != null);
List<Customer> Clistfiltered1 = Clist.parallelStream().filter(customerNotNullPredicate).collect(Collectors.toList());
List<License> Llistfiltered1 = Llist.parallelStream().filter(licenseNotNullPredicate).collect(Collectors.toList());
Clistfiltered1.retainAll(Llistfiltered1);
try {
Clistfiltered1.get(0);
} catch (Exception e){
System.out.println(e);
}
Run Code Online (Sandbox Code Playgroud)
当然,retainAll()不返回任何内容,因为两个列表只包含不同类型的对象。我如何尝试使用retainAll()对象的特定属性?
非常感谢您提前。
您的任务描述不清楚,但显然,您想要获取所有Customer实例,其中存在License具有相同实例的实例id。
虽然可以将其描述为一个流操作,但在一个列表中为另一个列表的每个元素搜索匹配项将意味着O(nxm)时间复杂度操作,换句话说,如果您有大列表,它的性能会非常糟糕。
因此,最好在具有O(n+m)时间复杂度的两个操作中进行:
List<Customer> cList = Customer.getAllCustomers();
List<License> lList = License.getAllLicenses();
Set<?> licenseIDs = lList.stream()
.map(l -> l.id).filter(Objects::nonNull)
.collect(Collectors.toSet());
List<Customer> cListFiltered = cList.stream()
.filter(c -> licenseIDs.contains(c.id))
.collect(Collectors.toList());
if(cListFiltered.isEmpty()) System.out.println("no matches");
else cListFiltered.forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)
虽然Set返回的确切类型collect(Collectors.toSet())未指定,但您可以期望它比线性查找更好,这允许contains在后续流操作中使用其方法。请注意,只有第一个操作具有null值过滤器;由于这保证licenseIDs集合不包含null,null因此隐式拒绝具有id 的客户。
获取公共 ID 很容易
Set<?> commonIDs = cList.stream()
.map(l -> l.id).filter(licenseIDs::contains)
.collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)
使用commonIDs,您可以根据需要过滤客户列表或许可证列表。
在这种情况下,您不能使用 keepAll() ,但我会像这样解决问题:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class DifferentCollections {
public static void main(String[] args) {
List<Customer> customers = new ArrayList<>(Arrays.asList(new Customer(1), new Customer(2), new Customer(10)));
List<License> licenses = new ArrayList<>(Arrays.asList(new License(1), new License(2), new License(30)));
List<Customer> filteredCustomers = customers.stream().
filter(c -> customerIdFoundInLicensesList(c, licenses)).
collect(Collectors.toList());
System.out.println(filteredCustomers);
}
private static boolean customerIdFoundInLicensesList(Customer customer, List<License> licenses) {
return licenses.stream().
filter(l -> l.getId().equals(customer.getId())).
findAny().
isPresent();
}
}
class Customer {
Integer id;
public Customer(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
@Override
public String toString() {
return "Customer{" + "id=" + id + '}';
}
}
class License {
Integer id;
public License(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
@Override
public String toString() {
return "License{" + "id=" + id + '}';
}
}
Run Code Online (Sandbox Code Playgroud)