繁体   English   中英

如何使用流过滤对象的属性?

[英]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);
}

问题是列表是空的,而您试图访问不存在的第一个元素。 您可以使用findAnyfindFirst返回可选以避免访问潜在的空对象,如果对象为空,则允许您设置默认值

return Building.Buildings
                .stream()
                .filter(x -> x.getBuildingPosition() == pos)
                .findAny().orElse(null);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM