【问题标题】:How to filter objects using streams by their attributes?如何通过属性使用流过滤对象?
【发布时间】:2019-12-08 15:34:26
【问题描述】:

各位程序员,大家好, 最近是学校,我们被要求学习流 API,我爱上了它们。不幸的是,我不够熟练,无法正确使用它们。我需要使用流通过它们各自的属性过滤大约 23 个建筑物(被视为对象)的低谷。让我演示一下: 这是我的建筑类:

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 对象的示例

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);
    }

它返回了一个异常 线程“主”java.lang.IndexOutOfBoundsException 中的异常:索引 0 超出长度 0 的范围。 好像我的 .filter() 写错了,所以它没有传递任何元素。

谁能告诉我如何正确过滤它?

【问题讨论】:

    标签: java arraylist filter java-stream


    【解决方案1】:

    首先您将建筑物添加到静态列表中,但您没有初始化此对象,这些字段都是空的

    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);
    }
    

    如果您只想返回一个满足您的过滤器的对象,请使用 findFirst 来返回一个 Optional

    public static Building getBuildingByPosition(int pos) {
        Optional<Building> building = Building.Buildings
        .stream()
        .filter(x -> x.getBuildingPosition() == pos)
        .findFirst();
        return building.orElse(null);
    }
    

    【讨论】:

    • 这就是问题所在,非常感谢。似乎这是 ArrayLists 的问题,而不是流的问题。
    • 另外,Optional 不起作用,因为您无法从 Optional 转换为 Building
    • @MikuldaKopecky where ?,如果你的意思是 getBuildingByPosition 方法,return 语句将 optional 转换为 building。指令 building.orElse(null) 表示如果存在则返回 building,否则返回 null。如果它在其他地方显示它提出问题的代码
    【解决方案2】:

    问题在以下行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"));
    }
    

    【讨论】:

    • 非常感谢,伙计。我只是担心我的过滤器不正确,但正如@billal GHILAS 提到的,这些值没有被初始化。您的回答确实使用了许多将在未来使用的新信息。谢谢!
    【解决方案3】:

    您的过滤器是正确的。我瘦了建筑类构造函数。请为过滤器设置成员变量。

    //constructor:
    public Building(int position, int cost, int rent, String color, int owner) {
        this.position = position;
        Buildings.add(this);
    }
    

    【讨论】:

      【解决方案4】:

      问题是列表为空,而您试图访问第一个不存在的元素。您可以使用返回 optionalfindAnyfindFirst 来避免访问可能为 null 的对象,如果该对象是空

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-19
        • 2019-08-22
        • 1970-01-01
        • 2019-05-29
        • 2020-04-21
        • 2019-01-17
        • 1970-01-01
        相关资源
        最近更新 更多