[英]How to filter objects using streams by their attributes?
大家好,我的程序员们,最近学校要求我们学习流 API,我爱上了他们。 不幸的是,我不够熟练,无法正确使用它们。 我需要使用流来过滤 23 个建筑物(被视为对象)周围的槽,它们各自的属性。 让我演示一下:这是我的 Building 课程:
class Building {
String color;
int position;
int cost;
int rent;
int owner;
//ArrayList for storing all of the buildings
public static ArrayList<Building> Buildings = new ArrayList<>();
//getter of the position of this building
public int getBuildingPosition() {
return position;
}
//constructor:
public Building(int position, int cost, int rent, String color, int owner) {
Buildings.add(this);
}
}
这是我的建筑对象的一个例子
Building buld1 = new Building(1, 50, 6, "gray", 0);
现在有趣的是,因为当我尝试通过此流代码对其进行过滤时:
public static Building getBuildingByPosition(int pos) {
List<Building> all = Building.Buildings
.stream()
.filter(x -> x.getBuildingPosition() == pos) // here may be the error
.collect(Collectors.toList());
return all.get(0);
}
它在线程“main” java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0 中返回异常Exception 。 似乎我的.filter() 写错了,所以它没有传递任何元素。
有人可以告诉我如何正确过滤它吗?
首先,您将 Building 添加到您的静态列表中,但您没有初始化此对象,这些字段都是空的
public Building(int position, int cost, int rent, String color, int owner) {
this.position = position;
this.cost = cost;
this.rent = rent;
this.color = color;
this.owner = owner;
Buildings.add(this);
}
如果您只想返回一个满足过滤器的对象,请使用返回 Optional 的 findFirst
public static Building getBuildingByPosition(int pos) {
Optional<Building> building = Building.Buildings
.stream()
.filter(x -> x.getBuildingPosition() == pos)
.findFirst();
return building.orElse(null);
}
问题出在以下行return all.get(0);
您尝试访问索引为 0 的元素,但列表为空,因为没有任何对象符合过滤条件。
如果在给定位置应该有 0 个或 1 个对象,那么您可以使用这样的写法:
public static Optional<Building> getBuildingByPosition(int pos) {
Optional<Building> buildingAtPos= Building.Buildings
.stream()
.filter(x -> x.getBuildingPosition() == pos)
.findFirst();
return buildingAtPos;
}
请注意,现在我们将 Building 包装在Optional
,这通常用于可能存在或不存在值的情况。
如果你总是想返回Building
或 null 如果没有任何建筑物你可以这样写,但第一个解决方案是建议的方法:
public static Optional<Building> getBuildingByPosition(int pos) {
Optional<Building> buildingAtPos= Building.Buildings
.stream()
.filter(x -> x.getBuildingPosition() == pos)
.findFirst();
return buildingAtPos.orElse(null);
}
如果您想强制该建筑物的存在,您可以使用的另一个选项:
public static Optional<Building> getBuildingByPosition(int pos) {
Optional<Building> buildingAtPos= Building.Buildings
.stream()
.filter(x -> x.getBuildingPosition() == pos)
.findFirst();
return buildingAtPos.orElseThrow(()-> new IllegalStateException("Building at position " + pos + " must exist"));
}
你的过滤器是正确的。 我瘦了 Building 类的构造函数。 请为过滤器设置成员变量。
//constructor:
public Building(int position, int cost, int rent, String color, int owner) {
this.position = position;
Buildings.add(this);
}
问题是列表是空的,而您试图访问不存在的第一个元素。 您可以使用findAny或findFirst返回可选以避免访问潜在的空对象,如果对象为空,则允许您设置默认值
return Building.Buildings
.stream()
.filter(x -> x.getBuildingPosition() == pos)
.findAny().orElse(null);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.