Como somar items iguais em lista?

pessoal,

A entrada de dados para minha aplicação é um arquivo excel. Cada linha representa um objeto da classe Component, cuja definição é:

[code]public class Component {

private String id;
private String partNumber;
private String mcId;
private Integer quantity;

public Component() {
}
// getters e setters
// hashcode e equals
// toString()

}[/code]

Não tenho como controlar a geração desse arquivo excel e pode acontecer da lista de Component resultante seja algo assim:

Component [id=1, partNumber=“A”, quantity=5]
Component [id=2, partNumber=“A”, quantity=3]
Component [id=3, partNumber=“B”, quantity=2]
Component [id=4, partNumber=B", quantity=7]

Como que eu consigo garantir que a lista seja algo do tipo

Component [id=2, partNumber=“A”, quantity=8]
Component [id=3, partNumber=“B”, quantity=9]

O método que eu tentei usa para isso é assim:

[code]private void eliminateDuplicateComponent() {
// lista original
List compList = componentList;

    // instanciação de mapa para organizar a lista de componentes
    Map<String, Component> componentMap = new HashMap<String, Component>();

    for (int i = 0; i < compList.size(); i++) {
        Component comp = compList.get(i);
        if (comp.getPartNumber().equals(
                componentMap.containsKey(comp.getPartNumber()))) {
            Component c = componentMap.get(comp.getPartNumber());
            c.setQuantity(c.getQuantity() + comp.getQuantity());
        } else {
            componentMap.put(comp.getPartNumber(), comp);
        }
    }
    componentList = new ArrayList<Component>(componentMap.values());
}[/code]

mas o retorno é:
Component [id=2, partNumber=“A”, quantity=3]
Component [id=3, partNumber=“B”, quantity=7]

alguma idéia de como fazer isso?

Grato,
Gustavo

Oi!

Algo em que eu pensei rapidamente, é fazer sua classe Component implementar o Comparator, sendo que faça a avaliação a partir do campo partNumber, já que pelo o que eu entendi, é ele que repete e é partir dele que tu deseja “agrupar”.

Feito isso, você usa Collections.sort(suaLista, new Component()) e terás sua lista organizada. A partir disso, você sabe que os itens repetidos estarão em sequencia, agora, use um objeto Iterator para percorrer sua lista.

Bom, agora você pode realizar a comparação e caso seja igual, soma o valor e remove ela, sempre a próxima, ou seja, a primeira vez em que repete o valor.
O Iterator permite você remover um objeto da lista em que ele está percorrendo.

Dá para melhor bastante essa implementação, estou dizendo meio na pressa, se eu tiver mais tempo paro e penso em algo mais apresentável.
Abraços.

Você já pensou em implementar a interface Comparator na sua classe Component?

eu faria algo ± assim.

for (int i = 0; i < compList.size(); i++) { Component comp = compList.get(i); String chave = comp.getPartNumber(); if (componentMap.get(chave) == null) { componentMap.put(chave, comp); } else { componentMap.get(chave).setQuantity(componentMap.get(chave).getQuantity() + comp.getQuantity()); } }

@nel, @gilmaslima,
A idéia do Comparator parece bem interessante. Mas eu não conheço essa interface, tenho que dar uma olhada.

@avsouza,
hmm, parece interessante! vou ver se funciona!

Oi!

Creio que isso seja a sua solução, a mais rápida, a melhor? É outra história, mas acredito que resolva sim seu problema:

[code] List components = new ArrayList();
components.add(new Component(“1”, “A”, 5));
components.add(new Component(“2”, “B”, 2));
components.add(new Component(“3”, “A”, 3));
components.add(new Component(“4”, “C”, 5));
components.add(new Component(“5”, “B”, 4));

	Collections.sort(components, new Component());
	
	Map<String, Component> map = new HashMap<String, Component>();
	for(Component c : components) {
		String key = c.getPartNumber();
		if(!map.containsKey(key)) {
			map.put(c.getPartNumber(), c);
		} else {
			Component comp = map.get(key);
			Integer quantity = comp.getQuantity() + c.getQuantity();
			comp.setQuantity(quantity);
		}
	}
	
	for(String key : map.keySet()) {
		Component c = map.get(key);
		System.out.println("Id: " + c.getId());
		System.out.println("PartNumber: " + c.getPartNumber());
		System.out.println("Quantity: " + c.getQuantity());
		System.out.println("##########################################");
	}[/code]

Implementando o Comparator…

[code]class Component implements Comparator {
private String id;
private String partNumber;
private Integer quantity;

public Component() {}

public Component(String id, String partNumber, Integer quantity) {
	this.id = id;
	this.partNumber = partNumber;
	this.quantity = quantity;
}

public String getId() {
	return id;
}

public String getPartNumber() {
	return partNumber;
}

public Integer getQuantity() {
	return quantity;
}

public void setQuantity(Integer quantity) {
	this.quantity = quantity;
}

@Override
public int compare(Component o1, Component o2) {
	return o1.getPartNumber().compareToIgnoreCase(o2.getPartNumber());
} 

}[/code]

Dois detalhes:

1 - Eu criei no construtor os sets e ainda criei um método set no Quantity só para agilizar o exemplo pra você, atente-se mais a lógica e como foi feito o comparator.
2 - O resultado do comparator ignora case sensitive, veja se pode ou não, ai é questão de você analisar.

Abraços.