Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 需要使用算法建议从列表中获取对象_Java_Algorithm - Fatal编程技术网

Java 需要使用算法建议从列表中获取对象

Java 需要使用算法建议从列表中获取对象,java,algorithm,Java,Algorithm,我有一个对象列表: 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("

我有一个对象列表:

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 List=new ArrayList();
增加(新MyObj(“名称1”,31));
添加(新MyObj(“名称1”,442));
添加(新MyObj(“名称2”,213));
增加(新MyObj(“名称1”,31));
添加(新MyObj(“名称2”,341));
增加(新MyObj(“名称3”,131));
我的目标是创建另一个列表,其中没有同名的对象。并将所有相同对象的值添加到新对象中

类似这样:
newmyobj(“name1”,31+442+31)


我无法想出正确的算法,如何获得所有“重复”对象?

如果您将
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);

您可以在一个额外的类中实现第二个列表。 然后,您可以编写一个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);
    }
}
公共类ListHandler{
私有列表=新的ArrayList();
私有ListHandler实例=null;
公共ListHandler getInstance(){
if(实例==null){
实例=新的ListHandler();
}
返回实例;
}
公共无效添加列表(MyObj objectToAdd){
对于(MyObj对象:列表){
if(obj.getName().equals(objectToAdd.getName())){
obj.addToValue(objectToAdd.getValue());
返回;
}
}
list.add(objectToAdd);
}
}

您需要使用类似以下Java代码的内容来迭代列表:

 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(字符串名称)
findDestinationItem(字符串名称)
addDestinationItem(字符串名称)
listDestinationItems()


您会发现这些映射非常好地映射到
map.contains()
map.get()
map.put()
map.entrySet()
。OO实现这一点的方法是使用
Map
字段,但您也可以将
Map
传递给这些方法,例如
haveSeen(Map seenItems,String name)

我将使用Map:

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())
。基本上就是根据名字把你的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));
然后从映射中获取值并将其转换为新的
MyObj列表

List<MyObj> newList = map.values().stream().collect(Collectors.toList());

newList.forEach(System.out::println);
您可以组合这些步骤,而不在两者之间使用贴图。但是我会让你决定。

重写
hashCode()
并使用
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());
    }
  }

这只是一个暗示,不是一个完整的答案。我建议在此基础上找出解决方案。

这似乎是streams的任务:

Map<String, MyObj> result = list.stream()
    .collect(Collectors.toMap(
        MyObj::getName,
        Function.identity(),
        (a, b) -> new MyObj(a.getName(), a.getValue() + b.getValue())));
您可以按如下方式简化上述收集代码:

Map<String, MyObj> result = list.stream()
    .collect(Collectors.toMap(
        MyObj::getName,
        Function.identity(),
        MyObj::merge));
您可以使用Java8(假设在
MyObj
中存在getter
getName
):


问题中似乎没有算法尝试。。。当
obj1.name.equals(obj2.name)
时,你试着看了多少?在给你这个任务之前,你的老师有没有把你介绍给
Map
班?这有什么帮助?你必须保留列表中项目的顺序吗?@slim我没有老师,为什么我需要地图?我的对象不止两个fields@BigCoach好的,您有一个字符串
名称
,您需要知道您以前是否见过它。考虑一下<代码> map <代码>可以帮助你解决这个问题。这并不能增加MyObjA中参数的值,这是一个很好的简单易懂的解决方案。我认为您应该在中添加
map
声明。e、 g.
Mapmap=newhashmap()
  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());
    }
  }
Map<String, MyObj> result = list.stream()
    .collect(Collectors.toMap(
        MyObj::getName,
        Function.identity(),
        (a, b) -> new MyObj(a.getName(), a.getValue() + b.getValue())));
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));
Collection<MyObj> myObjects = results.values();
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());