Java Stream代码改进

时间:2016-10-20 11:40:33

标签: java collections java-8 java-stream

我有一张汽车Map<String, List<Car>>的地图,可以通过getCarsMap()方法返回,其中key是汽车的型号,价值是相同车型的汽车列表。

我想改进Car addCar(Car car)功能。现在我写了一些丑陋的代码和平

public Car addCar(Car car) {
    if(getCarsMap().entrySet().stream().anyMatch(es -> es.getKey().equals(car.getModel()))){
        if(!getCarsMap().get(car.getModel()).contains(car)){
            getCarsMap().get(car.getModel()).add(car);
        }
    }else{
        List<Car> tmpList = new ArrayList<Car>();
        tmpList.add(car);
        getCarsMap().put(car.getModel(), tmpList) ;
    }
    return car;
}

此外,需要为removeCar(Car car)编写类似的内容,但希望以一些不错的addCar方法作为模板更容易。

3 个答案:

答案 0 :(得分:1)

我的想法 - 依赖于Map的计算method

所以我的方法populateMapWith根据你的情况处理当前地图:

  • 如果值列表为空 - 创建新的,添加元素,添加到地图

  • 如果存在,只需将元素添加到当前列表

以及removeFromMap根据删除。

我用Object类来说明它,只是为了简化案例

public class BaseTest {

    private Map<String, List<Object>> myMap = new HashMap<>();

    @Test
    public void testName() throws Exception {
        Object car1 = new Object() {
            @Override
            public String toString() {
                return "car1";
            }
        };

        Object car2 = new Object() {
            @Override
            public String toString() {
                return "car1";
            }
        };

        populateMap(car1);
        populateMap(car2);

        assertEquals(2, myMap.get("car1").size());

        removeFromMap(car2);

        assertEquals(1, myMap.get("car1").size());
    }

    private void populateMap(Object o) {
        myMap.computeIfAbsent(o.toString(), key -> new ArrayList<>()).add(o);
    }

    private void removeFromMap(Object o) {
        myMap.computeIfPresent(o.toString(), (key,list) -> { list.remove(o); return list;});
    }
}

UPD:与Holger

讨论后的改进方法

答案 1 :(得分:1)

if(!getCarsMap().get(car.getModel()).contains(car))

您似乎不希望有重复项。因此,您必须使用不添加重复元素的Set而不是List,例如:

Map<String, Set<Car>> carmap = getCarsMap();
  

getBoatsMap().put(car.getModel(), tmpList) ;

这没有意义。把车放在应该有船的地图上是令人困惑的。但是,我假设要继续使用它。

所以我们可以:

Set<Cars> tempcar = new HashSet<>();
tempcar.add(car);
getBoatsMap().put(car.getModel(),tempcar);
  

public Car addCar(Car car)

addCar方法的返回类型。方法返回它操作的对象。这里,操纵地图而不是对象。它应该是这样的:

public Map<String,Set<Car>> addCar(Car car)

所以我们可以得到以下代码:

 public HashMap<String,Set<Car>> addCar(Car car){
        Map<String, Set<Car>> carmap = getCarsMap();
        if(carmap.containsKey(car.getModel())){
            HashSet<Car> carset = carmap.get(car.getModel());
            carset.add(car);
            map.put(car.getModel(),carset);
        }else{
            carmap = getBoatsMap();
            Set<Cars> tempcar = new HashSet<>();
            tempcar.add(car);
            carmap.put(car.getModel(),tempcar);
        }
        return carmap;
   }

这可以是您继续前进的基本模板。但是,这也可以进一步优化。对Java Collections API和Java 8的深入研究可以为您提供更好的想法。

对于removeCar(),方法签名可以是:

public Car removeCar(Car) 

<强>更新 我在评论中看到getBoatsMap()是一个错误。 所以代码是:

public Map<String, Set<Car>> addCar(Car car){
    Map<String, Set<Car>> carmap = getCarsMap();
    if(carmap.containsKey(car.getModel())){
        HashSet<Car> carset = carmap.get(car.getModel());
        carset.add(car);
        map.put(car.getModel(),carset);
    }else{
        Set<Cars> tempcar = new HashSet<>();
        tempcar.add(car);
        carmap.put(car.getModel(),tempcar);
    }
    return carmap;
}

答案 2 :(得分:1)

提示:

  • 使用Set代替List,因为Set不允许重复。

  • 使用contains检查元素是否在集合中,无论如何 是List还是Set。 (Car类必须使用equals方法来比较字段值。)

  • 返回boolean以指示集合是否已修改为 操作的结果。这就是Java集合所做的事情。

代码:

public boolean addCar(Car car) {
    Map<String, Set<Car>> carsMap = getCarsMap();
    if (!carsMap.containsKey(car.getModel())) {
        carsMap.put(car.getModel(), new HashSet<>(Arrays.asList(car)));
        return true;
    }
    if (!carsMap.get(car.getModel()).contains(car)) {
        return carsMap.get(car.getModel()).add(car);
    }
    return false;
}