我们假设我有一个HashMap,它将Fruit
作为其键,将Cars
的ArrayList作为其值。
Fruit
是一个String name, int height, int width
的对象。 Car
是String 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
对象。
答案 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);