2015-11-12 6 views
2

Быстрый вопрос. Предположим, что у меня есть функция total (List List), и у меня есть класс MyObject, который имеет строку String и int, показанную ниже, и я хочу сравнить две разные строки объектов в моем общем методе. Если они совпадают, добавьте значение для обоих из них. В противном случае ничего не делайте.Есть ли способ сравнить два объекта в списке и объединить их наиболее оптимальные значения (Java)

Например, данные {[Johanna, 200], [Jack, 205], [Johanna, 100], [Jack, 50]};

Выход должен быть похож на {[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)); 
    } 
} 
+1

Что такое '' Order' в итератора '? Кроме того, в каком классе есть метод «total», поскольку он написан после закрытия класса MyObject? –

+0

Как работает 'Collections.sort()', если вы не дадите 'compareTo', который обеспечивает общий порядок? –

+0

У меня уже есть эти функции, даже итератор. Просто выяснить, есть ли все-таки, чтобы сравнить две вещи без повторения пунктов, которые уже были вызваны? Также я исправил код для некорректных имен и типов – Sleek13

ответ

1

Не существует способа, который является «наиболее оптимальным», поскольку он зависит от того, насколько велики данные. Проблема кажется подходящей для уменьшения карты, но если у вас есть только 4 элемента, тогда накладные расходы не оправдывают реального алгоритма сокращения карты.

Так или иначе, вот одна альтернатива, предварительно 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; 
} 
1

Вы можете уменьшить от n^2 до n*(n/2) с помощью

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

Но поскольку список отсортирован, это O (N). –

+0

Не имеет значения, отсортирован ли список. И 'O (n * (n/2)) = O (n^2)'. Я говорил о сокращении итераций. – Hannes

+0

Вы можете достичь 'O (n)' путем преобразования времени в пространство, используя один для цикла и карты. Для чтения и установки это возможно нечто вроде '2n + kn'. – Hannes

2

Вы можете сделать суммирование и сравнений параллельно без необходимости сортировки первого использования потоков.

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

Я пробовал это, но mo -> mo.value не работает, потому что компилятор думает, что mo имеет тип Object. Я должен указать mo как MyObject, например: (MyObject mo) -> mo.value – RichN

+0

Он работает для меня как есть. Java 8 делает вывод типа, поэтому он должен знать, что элементы потока из списка имеют тип MyObject. Вы используете мой точный код, включая определение newList? – WillShackleford

+0

или http://ideone.com/PZNDiP - прямой сборщик для сопоставления ('.collect (Collectors.toMap (o -> o.name, o -> o.value, Integer :: sum))') - это tad проще группировать по имени и объединять номера отдельно. @RichN Может подтвердить (см. Http://ideone.com/zVM1sY), что этот код работает. Старые версии Java 8/более старые версии Eclipse (Луна довольно плохая с лямбдами, Марс туда добирается) не знал всех трюков вывода типа и может вызвать проблемы. – zapl

Смежные вопросы