简体   繁体   中英

Is there a way to compare two objects in a List and combine their values that is most optimal?(Java)

Quick question. Suppose I have a function total (List list) and I have a MyObject class that have a String and an int displayed below and I want to compare two different object Strings in my total method. If they are the same, add the value on both of them. Otherwise, do nothing.

For example data is {[Johanna, 200], [Jack, 205], [Johanna, 100], [Jack, 50]};

The output should look like {[Johanna, 300], [Jack, 255]};

public static class MyObject {
   int value;
   String name;
   public MyObject(String nm, int val)
   {
       name = nm;
       value = val;
   }
}

public void total(List<MyObject> list) {
    List<MyObject> newList = new ArrayList<MyObject>();
    Collections.sort(list);
    Iterator<Order> ItrL = list.iterator();
    int index = 0;

    while(ItrL.hasNext())
    {

        MyObject compare = ItrL.next();
        Iterator<MyObject> ItrR = list.listIterator(index);
        index++;

        while (cmp.name.equals(ItrR.next().name)))
            newList.add(new MyObject(cmp.name, cmp.value + ItrR.value));
    }
}

You can do summing and comparisons in parallel with no need to sort first using streams.

List<MyObject> newList = Arrays.asList(
      new MyObject("Johanna", 200), 
        new MyObject("Jack", 205), 
        new MyObject("Johanna", 100),
        new MyObject("Jack", 50)
);
Map<String,Integer> map =
        newList.stream().parallel()
        .collect(Collectors.groupingBy(mo -> mo.name, 
                Collectors.summingInt(mo -> mo.value)));
System.out.println("map = " + map);

You can reduce from n^2 to n*(n/2) by using

for(int i = 0 ...
   for(int j = i + 1 ...

There is no method that is "most optimal" as it depends on how big the data is. The problem seems suitable for map-reduce, but if you have like only 4 elements, then the overhead cost doesn't justify a real map reduce algorithm.

So anyway, here's one alternative that is pre-Java 8 (list doesn't need to be sorted first):

public static Map<String, Integer> total(List<MyObject> list) {
    Map<String, Integer> result = new HashMap<String, Integer>();

    for (MyObject myObject : list) {
        Integer prevValue = result.get(myObject.name);
        if (prevValue == null) {
            result.put(myObject.name, myObject.value);
        } else {
            result.put(myObject.name, myObject.value + prevValue);
        }
    }

    return result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM