[英]Compare two List<E> regardless of order
我有兩個E類型列表List list1,List list2。 E對象是一個POJO類,其中包含以下數據行。 兩個列表都包含相同的數據。 例如,在最后一列中,如果我將false更改為true,則無法檢測到。
| 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;
}
一種更好的方法(假設列表不包含重復的值)是將一個列表的所有元素存儲在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)
基本上,如果大小相等,你可以只遍歷兩個列表,當你發現在第一狀態expectedStatuses
未在發現actualStatuses
因為名單是不相等了,那么你可以返回false。
但是,如果列表變大,則可能會遇到性能問題,因為這基本上是O(n 2 )方法。 在這種情況下,您可以先將所有預期狀態放入一組,然后再刪除實際狀態。 如果最后該集合不為空,則列表不相等,您甚至會知道缺少哪些狀態。 如果只需要檢查是否相等,則只需檢查集合是否包含第二個列表的元素即可。 在最壞的情況下,兩者均為O(n)。
請注意, List.containsAll()
操作與上述基本相同,即遍歷collection參數,並且每個元素都在其自己的列表中查找(調用contains(e)
),在第一個未找到的元素上返回false。
編輯:
如果您的元素具有正確實現的hashCode()
和equals()
,則使用set就像List.containsAll()
一樣簡單:
new HashSet<Status>( expectedStatuses ).containsAll( actualStatuses );
關於什么:
private boolean compareLists(List<Status> actualStatuses, List<Status> expectedStatuses) {
boolean listsHaveSameSize = actualStatuses.size() == expectedStatuses.size();
return listsHaveSameSize ? actualStatuses.containsAll(expectedStatuses)
: false;
}
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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.