Java 更新集合中的项目

Java 更新集合中的项目,java,performance,collections,Java,Performance,Collections,我有一个Java中对象的集合,我需要获取一个特定的项来更新它的属性。我可以使用stream和filter获取项目并对其进行更新,也可以使用.remove()和.add()替换旧对象 我的问题是,哪一种方法的性能更好,一般来说,每种方法的优缺点是什么 e、 g publicstaticvoidmain(字符串[]args) { 收集车=新的ArrayList(); 添加(新车(1,“福特”,“浮动”10000); 增加(新车(2辆,“菲亚特”(浮动)15000); 添加(新车(2辆,“宝马”,浮

我有一个Java中对象的
集合
,我需要获取一个特定的项来更新它的属性。我可以使用
stream
filter
获取项目并对其进行更新,也可以使用
.remove()
.add()
替换旧对象

我的问题是,哪一种方法的性能更好,一般来说,每种方法的优缺点是什么

e、 g


publicstaticvoidmain(字符串[]args)
{
收集车=新的ArrayList();
添加(新车(1,“福特”,“浮动”10000);
增加(新车(2辆,“菲亚特”(浮动)15000);
添加(新车(2辆,“宝马”,浮动)20000);
//方法1
汽车更新Car=新车(2,“菲亚特”,浮动35000);
Car newCar=cars.stream().filter(c->c.getId().equals(updateCar.getId()).collect(toList()).get(0);
newCar.setPrice(updateCar.getPrice());
//方法2
汽车更新Car=新车(2辆,“菲亚特”(浮动)15000);
汽车。移除(更新汽车);
updateCar.setPrice((浮动)35000);
cars.add(updateCar);
}

你看得不对:在考虑性能时,你的切入点应该是时间复杂性。然后您可以深入研究实现细节

在您的例子中,这两个方法都以O(n)运行


如果性能如此重要,请使用O(1)算法,例如使用
HashMap你看得不对:考虑性能时,你的切入点应该是时间复杂度。然后您可以深入研究实现细节

在您的例子中,这两个方法都以O(n)运行


如果性能如此重要,请使用O(1)算法,例如使用
HashMap解决方案3:使用地图按其ID存储每辆车。这是ID的目标,正确使用它

因此,更新只需要map.get(id).setPrice(newprice)


另一个注意事项:当您想要获取一个潜在元素时,不要使用collect()。 流具有用于并行方法的findFirst()或findAny()。 所以


将具有更好的性能。

解决方案3:使用地图按其ID存储每辆车。这是ID的目标,正确使用它

因此,更新只需要map.get(id).setPrice(newprice)


另一个注意事项:当您想要获取一个潜在元素时,不要使用collect()。 流具有用于并行方法的findFirst()或findAny()。 所以


将具有更好的性能。

如果ID不唯一,则您提出的方法1将不准确。例如,如果你想换宝马,你会换菲亚特,因为他们有相同的id

无论如何,最有效的方法可能是既不过滤也不删除/插入,而是更新,除非您的对象是不可变的,或者您使用了
Set


如果您真的关心性能,您应该使用唯一的ID和
映射
,而不仅仅是
集合
,如果ID不是唯一的,您提出的方法1将不准确。例如,如果你想换宝马,你会换菲亚特,因为他们有相同的id

无论如何,最有效的方法可能是既不过滤也不删除/插入,而是更新,除非您的对象是不可变的,或者您使用了
Set


如果您真的关心性能,那么应该使用唯一的ID和
映射
,而不是单纯的
集合

这两者都不会产生性能,因为时间复杂度将为O(n)。如果您真的从性能的角度来看,请使用HashMap put和get。它将始终给出O(1)

例如:

映射put和get时间复杂度始终为O(1)

Map carsMap=newhashmap();
汽车平均价格(1辆,新车(1辆,“福特”,“浮动”10000);
汽车平均价格(2辆,新车(2辆,菲亚特)(浮动)15000);
//汽车更新价值
Car newCar=carsMap.get(2);
新车定价((浮动)35000);
carsMap.put(2辆新车);

两者都不会产生性能,因为时间复杂度为O(n)。如果您真的从性能的角度来看,请使用HashMap put和get。它将始终给出O(1)

例如:

映射put和get时间复杂度始终为O(1)

Map carsMap=newhashmap();
汽车平均价格(1辆,新车(1辆,“福特”,“浮动”10000);
汽车平均价格(2辆,新车(2辆,菲亚特)(浮动)15000);
//汽车更新价值
Car newCar=carsMap.get(2);
新车定价((浮动)35000);
carsMap.put(2辆新车);

您的两种方法在性能方面都没有多大意义

方法1 一个直接的解决办法是

    Integer idToUpdate = 2;
    float newPrice = 35000;
    cars.stream()
        .filter(c -> idToUpdate.equals(c.getId()))
        .forEach(car -> car.setPrice(newPrice));
方法2 由于
Car
的相等性仅基于ID,因此无需使用旧属性初始化新的
Car
实例

请注意,由于您没有指定集合类型,我们不知道它是否包含重复项。因此,直截了当的变体是

    Car updateCar = new Car(2, "Fiat", 35000);        
    do {} while(cars.remove(updateCar));
    cars.add(updateCar);
或者,为了确保出现的次数不会改变:

    Car updateCar = new Car(2, "Fiat", 35000);
    int num = 0;
    while(cars.remove(updateCar)) num++;
    cars.addAll(Collections.nCopies(num, updateCar));
但这仍然可能会更改集合元素的顺序(如果特定集合类型具有顺序)


显然,第一个变体要简单得多,并且保留源集合的属性,这比微小的性能差异更重要。除非集合是一个
集合
,否则这两个操作都意味着线性开销,可以通过使用从id到实例的映射来避免这种开销。

您的两种方法在性能方面都没有多大意义

方法1 一个直接的解决办法是

    Integer idToUpdate = 2;
    float newPrice = 35000;
    cars.stream()
        .filter(c -> idToUpdate.equals(c.getId()))
        .forEach(car -> car.setPrice(newPrice));
方法2 由于
Car
的相等性仅基于ID,因此无需使用旧属性初始化新的
Car
实例

请注意,由于您没有指定集合类型,我们不知道它是否包含重复项。因此,直截了当的变体是

    Car updateCar = new Car(2, "Fiat", 35000);        
    do {} while(cars.remove(updateCar));
    cars.add(updateCar);
或者,确保事件的数量不会改变
    Integer idToUpdate = 2;
    float newPrice = 35000;
    cars.stream()
        .filter(c -> idToUpdate.equals(c.getId()))
        .forEach(car -> car.setPrice(newPrice));
    Car updateCar = new Car(2, "Fiat", (float)15000); // unnecessary use of old values
    cars.remove(updateCar);
    updateCar.setPrice((float)35000);// just to update the property
    cars.add(updateCar);
    Car updateCar = new Car(2, "Fiat", 35000);        
    do {} while(cars.remove(updateCar));
    cars.add(updateCar);
    Car updateCar = new Car(2, "Fiat", 35000);
    int num = 0;
    while(cars.remove(updateCar)) num++;
    cars.addAll(Collections.nCopies(num, updateCar));