我有一个对象列表:
class MyObj{
String name;
int value;
...
}
此列表中的对象可以使用相同的名称,但值不同。
List<MyObj> list = new ArrayList<>();
list.add(new MyObj("name1", 31));
list.add(new MyObj("name1", 442));
list.add(new MyObj("name2", 213));
list.add(new MyObj("name1", 31));
list.add(new MyObj("name2", 341));
list.add(new MyObj("name3", 131));
我的目标是创建另一个List,没有具有相同名称的对象。并将所有相同对象的值添加到新对象中。
像这样:new MyObj("name1", 31+442+31)
......
我无法提出正确的算法,如何让所有&#34;重复&#34;对象
答案 0 :(得分:3)
我会使用地图:
map = new HashMap()
for el in list:
if map.get(el.name) == null:
map.put(el.name, el)
else
map.put(el.name, new El(el.name, el.value + map.get(el.name).value))
result = map.values()
此算法的复杂性O(n*hashCodeOfString())
。它基本上是O(n)
答案 1 :(得分:3)
根据名称将MyObj
收集到地图中。如果名称相同,则组合值:
Map<String,MyObj> map = list.stream()
.collect(Collectors.toMap((MyObj o) -> o.name, myObj -> myObj, (MyObj o1, MyObj o2) -> new MyObj(o1.name, o1.value + o2.value)));
map.forEach((k,v) -> System.out.println(k + " " + v));
打印
name3 MyObj [name=name3, value=131]
name2 MyObj [name=name2, value=554]
name1 MyObj [name=name1, value=504]
然后从地图中获取值并将其转换为MyObj
List<MyObj> newList = map.values().stream().collect(Collectors.toList());
newList.forEach(System.out::println);
打印
MyObj [name=name3, value=131]
MyObj [name=name2, value=554]
MyObj [name=name1, value=504]
您可以组合这些步骤,而不是在两者之间使用地图。但是我会把它留给你。
答案 2 :(得分:2)
您需要使用类似Java-ish伪代码的方式遍历列表:
for(MyObj item : list) {
String name = item.getName();
if(haveSeen(name) {
MyObj destinationItem = findDestinationItem(name);
destinationItem.setValue(destinationItem.getValue() + item.getValue());
} else {
addDestinationItem(copy(item));
}
}
return listDestinationItems();
剩下的问题是如何实施haveSeen(String name)
,findDestinationItem(String name)
,addDestinationItem(String name)
和listDestinationItems()
。
您会发现这些地图非常适合Map.contains()
,Map.get()
,Map.put()
和Map.entrySet()
。 OO方法是使用Map
字段,但您也可以将Map
传递给这些方法,例如haveSeen(Map<String,MyObj> seenItems, String name)
。
答案 3 :(得分:2)
覆盖hashCode()
并使用HashSet<MyObj>
合并相同的对象。迭代hashSet
并将它们放入新列表中。
class MyObj {
private String name;
private int value;
// other fields
// ....
// getter and setter
@Override
public int hashCode() {
return this.getName().hashCode();
}
@Override
public boolean equals(Object other) {
if(other == null) {
return false;
}
if(!(other instanceof MyObj)) {
return false;
}
if(this == (MyObj) other) {
return true;
}
return this.getName().equals(((MyObj)other).getName());
}
}
这是一个暗示,而不是一个完整的答案。我建议根据这个找出解决方案。
答案 4 :(得分:1)
您可以在额外的课程中实现第二个列表。 然后你可以编写一个add函数,如果一个具有相同名称的对象已经在那里,则搜索列表。 如果是,则将新值添加到当前值,如果没有将新项添加到列表中。
public class ListHandler {
private List<MyObj> list = new ArrayList<>();
private ListHandler instance = null;
public ListHandler getInstance() {
if (instance == null) {
instance = new ListHandler();
}
return instance;
}
public void addToList(MyObj objectToAdd) {
for (MyObj obj : list) {
if (obj.getName().equals(objectToAdd.getName())) {
obj.addToValue(objectToAdd.getValue());
return;
}
}
list.add(objectToAdd);
}
}
答案 5 :(得分:1)
这似乎是溪流的任务:
setDT(data_ARIMA, keep.rownames = TRUE)[]
data_ARIMA$dates_intermediate <- date_decimal(as.numeric(data_ARIMA$rn))
data_ARIMA$dates <- as.Date(date_decimal(as.numeric(data_ARIMA$rn)))
data_ARIMA
这里我使用Collectors.toMap
实用程序,它通过确定映射的键和值来收集流的元素,接受用于在键相等时合并元素的合并函数
如果您的Map<String, MyObj> result = list.stream()
.collect(Collectors.toMap(
MyObj::getName,
Function.identity(),
(a, b) -> new MyObj(a.getName(), a.getValue() + b.getValue())));
班级有此方法:
MyObj
您可以按照以下方式简化上面的收集代码:
public MyObj merge(MyObj another) {
return new MyObj(this.getName(), this.getValue() + another.getValue());
}
最后,您已在地图的值中拥有Map<String, MyObj> result = list.stream()
.collect(Collectors.toMap(
MyObj::getName,
Function.identity(),
MyObj::merge));
集合:
MyObj
答案 6 :(得分:1)
您可以使用Java8(假设getName
中存在getter MyObj
):
list.stream()
//map names to sum of values associated with them
.collect(Collectors.groupingBy(MyObj::getName, Collectors.reducing(0, MyObj::getValue, Integer::sum))).entrySet()
//transform map to stream of MyObj
.stream().map(e->new MyObj(e.getKey(), e.getValue()))
//collect into list
.collect(Collectors.toList());
答案 7 :(得分:0)
如果您将hashCode
和equals
添加到MyObj
课程,则可以通过这种方式获得不同的列表:
Map<MyObj, MyObj> map = list.stream()
.collect(Collectors.toMap(Function.identity(),
obj -> obj,
(a, b) -> new MyObj(a.name, b.value + a.value)));
map.values()
.forEach(System.out::println);
返回:
MyObj [name=name3, value=131]
MyObj [name=name2, value=554]
MyObj [name=name1, value=504]