如果满足条件

时间:2018-03-18 21:48:57

标签: java hashmap

我们假设我有一个HashMap,它将Fruit作为其键,将Cars的ArrayList作为其值。

Fruit是一个String name, int height, int width的对象。 CarString name, String FruitItRunsOver, int weight的对象。

我应该将在这个水果上运行的水果和汽车添加到我的HashMap中。我最初按顺序给予水果然后按顺序给我汽车。

现在,我遇到的问题是,我知道一个Car由FruitItRunsOver成员变量运行的果实,正如你可能猜到的那样,它将与Fruit的名称相同。最初,我得到了水果,而且在给予他们的时候,我put(Fruit, new ArrayList<Car>())

然而,一旦我上车,我想知道添加它们的最佳方法是什么?我很想得到像这样的东西:

for (Fruit f : hashmap.keySet()) {
    if (f.getName().equals(car.getFruit())) {
        ArrayList<Car> cars = hashmap.get(f);
        cars.add(car);
        hashmap.put(f, cars)
    }
}

..但我认为这看起来很恶劣。我以为我可以拥有钥匙,而不是水果,是水果的名字。但请记住,我需要保存水果的其他成员变量。我稍后会在代码中需要它们。那么,我应该有一个嵌套的HashMap?如果是这样,结构应该如何?

由于

编辑:我想这是我的错,因为没有澄清。 car.getFruit()将返回水果名称FruitItRunsOver,而不是Fruit对象。

3 个答案:

答案 0 :(得分:1)

制作Map<String,Fruit>以将水果名称映射到Fruit个对象。如果您计划不对水果到汽车地图进行进一步修改,或者您可以在计划运行期间保留该地图,则此地图可能是暂时的:

Map<String,Fruit> fruitByName = new HashMap<>();
for (Fruit fruit : allFruits) {
    fruitByName.put(fruit.getName(), fruit);
}
Map<Fruit,List<Car>> carByFruit = new HashMap<>();
for (Car car : allCars) {
    Fruit f = fruitByName.get(car.getFruit());
    if (f == null) {
        ... // Throw an exception
    }
    List<Car> cars = carByFruit.get(f);
    if (cars == null) {
        cars = new ArrayList<Car>();
        carByFruit.put(f, cars);
    }
    cars.add(car);
}

您还可以使用额外的Map<String,FruitAndItsCars>类创建FruitAndItsCars,以将Fruit对象与List<Car>对象列表合并。

答案 1 :(得分:1)

您可以使用computeIfAbsent

方法computeIfAbsent作为第一个参数接收密钥,第二个参数接收Function(一个参数的函数)。此函数接收密钥并仅在密钥不存在时执行,然后它应返回该值。在这种情况下,当钥匙不存在时,汽车的空列表,以及当它存在时的当前汽车列表。然后添加新车。

Fruit carFruit = getFruitByName(car.getFruit());
hashmap.computeIfAbsent(carFruit, (fruit) -> new ArrayList<>()).add(car);

这样你就不需要for循环,并且当密钥不存在时你已经处理了这个案例,添加了新的列表。

要通过名称获取水果,如果您只有一个水果集合,您可以使用java的流创建地图,此地图有一个字符串,其名称为key,Fruit itseld为值:

Map<String, Fruit> fruitByName = getFruits() // however that you get all the fruits 
                                             // e.g. hashmap.keySet()
    .stream()
    .collect(Collectors.toMap(Fruit::getName, Function.identity()));

拥有此地图Map<String, Fruit>,您可以通过简单调用fruitByName.get(fruitName)替换方法getFruitByName()

注意:您通常应该定义equals()hashcode()方法以将对象用作关键字,在这种情况下为Fruit

编辑: 使用安迪特纳的消息

答案 2 :(得分:1)

对于你添加的每辆车,你都会对水果进行迭代,它效率不高,并且在某种程度上反直觉,因为你有一个Map可以通过密钥直接访问。

使用汽车作为字段表示水果的相同值作为关键字会更有效。如果合适,请使用字符串FruitItRunsOver

Map<String, List<Car>> carsByFruitName = new HashMap<>();
// populate the map with Fruit name and empty ArrayList
..

// for each car to create, retrieve the List of Car from the String name representing the fruit 
List<Car> cars = carsByFruitName.get(car.getFruitItRunsOver());
cars.add(car);