2015-07-14 2 views
1

У меня есть два списка типов E Список list1, Список list2. Объект E является классом POJO, который содержит строку следующих данных. Оба списка содержат одинаковые данные. Например, в последнем столбце, если я изменю false на true, он не сможет обнаружить.Сравнить два списка <E> независимо от порядка

| statusId | statusName        | statusState | isRequire   | 
| 3   | Approved         | APPROVED | false    | 
| 201  | Attributed        | REJECTED | true     | 
| 202  | Denied         | REJECTED | false    | 
| 204  | Fraud          | REJECTED | false    | 
| 205  | Insufficient        | REJECTED | false    | 
| 206  | Invalid         | REJECTED | false    | 
| 207  | Cancelled         | REJECTED | false    | 
| 208  | Cannot traced        | REJECTED | false    | 
| 209  | Transaction online      | REJECTED | false    | 
| 210  | Voucher         | REJECTED | false    | 
| 211  | does not meet req       | REJECTED | false    | 

Я хочу написать функцию так, чтобы, если данные, эти два списка отличаются друг от друга, то это может быть обнаружено. Следующий мой код, но кажется, что он всегда дает «false», являются ли данные одинаковыми или разными в обоих списках.

private boolean compareLists(List<Status> actualStatuses, List<Status> expectedStatuses) { 
    boolean indicator = false; 
    if (actualStatuses!= null && expectedStatuses!=null && actualStatuses.size() == expectedStatuses.size()){ 
     for (Status expectedStatusData : expectedStatuses){ 
      for(Status actualStatusData : actualStatuses){ 
       if(actualStatusData.getStatusId() == expectedStatusData.getStatusId() 
         && actualStatusData.getStatusName().equals(expectedStatusData.getStatusName()) 
         && actualStatusData.getStatusState().equals(expectedStatusData.getStatusState()) 
         && actualStatusData.isEnable() == expectedStatusData.isEnable() 
         && actualClaimStatusData.isRequire() == expectedStatusData.isRequire()){ 
        indicator = true; 
        break; 
       } 
       else indicator = false; 
      } 
     } 
     if (indicator) 
      return true; 
    } 
    else 
     return false; 

    return indicator; 
} 
+2

Вы лучше иметь 'equals' (+ 'hashCode') переопределяются в вашем классе' Status', поэтому вы можете избежать этой большой строки 'if', и ваш код будет намного читабельнее. –

ответ

0

насчет:

private boolean compareLists(List<Status> actualStatuses, List<Status> expectedStatuses) { 
    boolean listsHaveSameSize = actualStatuses.size() == expectedStatuses.size(); 

    return listsHaveSameSize ? actualStatuses.containsAll(expectedStatuses) 
          : false; 
} 
+0

Не работает ни – ahadcse

+0

Должен работать, если ваши объекты реализуют 'hashCode()' и 'equals()' правильно. – Crazyjavahacking

1

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

Однако, если списки увеличиваются, вы можете столкнуться с проблемами производительности, поскольку это в основном подход O (n). В этом случае вы можете сначала поместить все ожидаемые статусы в набор и затем удалить фактические. Если в конце набор не пуст, списки не равны, и вы даже знаете, какие статусы отсутствуют. Если вам нужно только проверить равенство, просто проверьте, содержит ли набор элементы второго списка. Оба были бы O (n) в худшем случае.

Отметим, что List.containsAll() в основном такой же, как описано выше, т.е. выполняет итерацию по параметру коллекции и для каждого элемента выглядит в своем собственном списке (вызов contains(e)), а на первом не найденном элементе возвращает false.

Edit:

С помощью набора будет столь же просто, как List.containsAll(), если ваши элементы имеют свои hashCode() и equals() реализованы должным образом:

new HashSet<Status>(expectedStatuses).containsAll(actualStatuses); 
4

Лучший способ сделать это (если предположить, что список Безразлично» t содержит повторяющиеся значения) заключается в том, чтобы сохранить все элементы одного списка в HashSet, а затем проверить, содержит ли HashSet все элементы другого списка и что их размеры одинаковы.

private <E> boolean listsHaveSameElements(final List<E> l1, final List<E> l2) { 
    final Set<E> set = new HashSet<>(l1); 
    return l1.size() == l2.size() && set.containsAll(l2); 
} 

Это O(n+m) решение при использовании List.containsAll() нужно будет перебирать все элементы другого списка, чтобы проверить наличие поэтому было бы O(n*m)

+1

ИМХО. Если значение hashcode и equals превышено, Set установит улучшение производительности. –

-1
public <T> boolean equalsIgnoreOrder(List<T> list1, List<T> list2) { 
    if (list1.size() != list2.size()) { 
     return false; 
    } 
    Map<T, Integer> map1 = createCountMap(list1); 
    Map<T, Integer> map2 = createCountMap(list2); 
    return map1.equals(map2); 
} 

/** 
* Note that T must have a proper hashCode() and equals() for this to work 
*/ 
private <T> Map<T, Integer> createCountMap(List<T> list) { 
    Map<T, Integer> map = new HashMap<T, Integer>(); 
    for (T value : list) { 
     Integer prevCount = map.get(value); 
     map.put(value, prevCount == null ? 1 : prevCount + 1); 
    } 
    return map; 
} 
+0

Почему голос? Из всех ответов это единственный, который фактически сравнивает два списка, игнорируя порядок, принимая во внимание дубликаты в каждом и отклоняя два списка с теми же элементами, но с разными дубликатами –

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