【问题标题】:Is there a way to compare two objects in a List and combine their values that is most optimal?(Java)有没有办法比较 List 中的两个对象并组合它们的最佳值?(Java)
【发布时间】:2015-11-12 22:28:19
【问题描述】:

快速提问。假设我有一个函数 total(列表列表),并且我有一个 MyObject 类,它有一个 String 和一个 int 显示在下面,我想在我的 total 方法中比较两个不同的对象字符串。如果它们相同,则将它们的值相加。否则,什么都不做。

例如数据是 {[约翰娜,200],[杰克,205],[约翰娜,100],[杰克,50]};

输出应该看起来像 {[约翰娜,300],[杰克,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));
    }
}

【问题讨论】:

  • Iterator&lt;Order&gt; 中的Order 是什么?还有,total方法在MyObject类关闭后写在哪个类中?
  • 如果您不提供提供总排序的compareToCollections.sort() 如何工作???
  • 我已经有了这些功能,甚至是迭代器。只是想知道是否可以在不重复已经调用的项目的情况下比较两件事?我还修复了一些不正确名称和类型的代码

标签: java compare


【解决方案1】:

您可以并行进行求和和比较,而无需先使用流进行排序。

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);

【讨论】:

  • 我试过这个,但是 mo -> mo.value 不能正常工作,因为编译器认为 mo 是 Object 类型。我必须像这样将 mo 指定为 MyObject: (MyObject mo) -> mo.value
  • 它对我有用。 Java 8 会进行类型推断,因此它应该知道由 List 生成的流的元素属于 MyObject 类型。您是否在使用我的确切代码,包括 newList 的定义?
  • ideone.com/PZNDiP - 直接收集器映射 (.collect(Collectors.toMap(o -&gt; o.name, o -&gt; o.value, Integer::sum))) 比按名称分组和单独合并数字要简单一点。 @RichN 可以确认(请参阅 ideone.com/zVM1sY)该代码有效。旧的 Java 8 版本/旧版本的 Eclipse(Luna 对 lambdas 的使用非常糟糕,Mars 正在使用它)不知道所有类型推断技巧并且可能会导致麻烦。
  • @zapl 确实是在 Luna 上,这可能是原因。我已经尝试了代码,它似乎可以正常工作。
【解决方案2】:

没有“最佳”的方法,因为它取决于数据的大小。该问题似乎适用于 map-reduce,但如果您只有 4 个元素,那么开销成本并不能证明真正的 map-reduce 算法是合理的。

所以无论如何,这是 Java 8 之前的一个替代方案(列表不需要首先排序):

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;
}

【讨论】:

    【解决方案3】:

    您可以通过使用从n^2 减少到n*(n/2)

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

    【讨论】:

    • 但是由于列表是排序的,所以是O(N)。
    • 列表是否排序无关紧要。和O(n*(n/2)) = O(n^2)。我说的是减少迭代。
    • 您可以通过使用一个for循环和一个映射将时间转换为空间来实现O(n)。它可能类似于 2n+kn 用于阅读和放置。
    • 排序列表的 O(N) 因为只有一个循环而不是两个循环。
    • 你是绝对正确的。如果列表是按照这种意义上排序的,那么彼此相等的对象就会相互跟随。
    猜你喜欢
    • 1970-01-01
    • 2013-04-18
    • 2020-03-06
    • 2015-11-14
    • 2022-10-17
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    相关资源
    最近更新 更多