Как я могу рассчитать разницу между двумя ArrayLists?
У меня есть два списка ArrayLists.
ArrayList A содержит
['2009-05-18','2009-05-19','2009-05-21']
ArrayList B Содержит ['2009-05-18','2009-05-18','2009-05-19','2009-05-19','2009-05-20','2009-05-21','2009-05-21','2009-05-22']
Мне нужно сравнить ArrayLst A и ArrayLst B. Результат ArrayList
должен содержать список, который не существует в ArrayList A.
Результат ArrayList должен быть
[ '2009-05-20', '2009-05-22']
как сравнить?
Ответы
Ответ 1
В Java вы можете использовать Collection
интерфейс removeAll
.
// Create a couple ArrayList objects and populate them
// with some delicious fruits.
Collection firstList = new ArrayList() {{
add("apple");
add("orange");
}};
Collection secondList = new ArrayList() {{
add("apple");
add("orange");
add("banana");
add("strawberry");
}};
// Show the "before" lists
System.out.println("First List: " + firstList);
System.out.println("Second List: " + secondList);
// Remove all elements in firstList from secondList
secondList.removeAll(firstList);
// Show the "after" list
System.out.println("Result: " + secondList);
Вышеприведенный код выдаст следующий результат:
First List: [apple, orange]
Second List: [apple, orange, banana, strawberry]
Result: [banana, strawberry]
Ответ 2
У вас уже есть правильный ответ.
И если вы хотите сделать более сложные и интересные операции между списками (коллекциями), используйте коллекцию коллекций apache (CollectionUtils)
Это позволяет вам делать конъюнкцию/дизъюнкцию, находить пересечение, проверять, является ли одна коллекция подмножеством других и других приятных вещей.
Ответ 3
В Java 8 с потоками все довольно просто. ОБНОВЛЕНИЕ: может быть эффективным без потоков, см. ниже.
List<String> listA = Arrays.asList("2009-05-18","2009-05-19","2009-05-21");
List<String> listB = Arrays.asList("2009-05-18","2009-05-18","2009-05-19","2009-05-19",
"2009-05-20","2009-05-21","2009-05-21","2009-05-22");
List<String> result = listB.stream()
.filter(not(new HashSet<>(listA)::contains))
.collect(Collectors.toList());
Обратите внимание, что хэш-набор создается только один раз: ссылка на метод привязана к его содержащему методу. Чтобы сделать то же самое с лямбдой, нужно было бы иметь набор в переменной. Создание переменной не является плохой идеей, особенно если вы считаете ее неприглядной или трудной для понимания.
Вы не можете легко опровергнуть предикат без чего-либо подобного этому вспомогательному методу (или явному приведению), поскольку вы не можете напрямую вызвать ссылку на метод отрицания (сначала необходим вывод типа).
private static <T> Predicate<T> not(Predicate<T> predicate) {
return predicate.negate();
}
Если бы у потоков был метод filterOut
или что-то подобное, это выглядело бы лучше.
Кроме того, @Holger дал мне идею. ArrayList
имеет метод removeAll
, оптимизированный для многократных удалений, он только один раз переставляет свои элементы. Однако он использует метод contains
, предоставляемый данной коллекцией, поэтому нам нужно оптимизировать эту часть, если listA
совсем не крошечный.
С ранее объявленными listA
и listB
этому решению не требуется Java 8, и он очень эффективен.
List<String> result = new ArrayList(listB);
result.removeAll(new HashSet<>(listA));
Ответ 4
EDIT: Исходный вопрос не указал язык. Мой ответ на С#.
Вместо этого вы должны использовать HashSet для этой цели. Если вы должны использовать ArrayList, вы можете использовать следующие методы расширения:
var a = arrayListA.Cast<DateTime>();
var b = arrayListB.Cast<DateTime>();
var c = b.Except(a);
var arrayListC = new ArrayList(c.ToArray());
используя HashSet...
var a = new HashSet<DateTime>(); // ...and fill it
var b = new HashSet<DateTime>(); // ...and fill it
b.ExceptWith(a); // removes from b items that are in a
Ответ 5
Я использовал Guava Sets.difference.
Параметры представляют собой множества, а не общие коллекции, но удобный способ создания наборов из любой коллекции (с уникальными элементами) - это Guava ImmutableSet.copyOf (Iterable).
(Я впервые разместил это по связанному/обдуманному вопросу, но я копирую его здесь, так как считаю, что это хороший вариант, который до сих пор отсутствует.)
Ответ 6
Хотя это очень старый вопрос в Java 8, вы можете сделать что-то вроде
List<String> a1 = Arrays.asList("2009-05-18", "2009-05-19", "2009-05-21");
List<String> a2 = Arrays.asList("2009-05-18", "2009-05-18", "2009-05-19", "2009-05-19", "2009-05-20", "2009-05-21","2009-05-21", "2009-05-22");
List<String> result = a2.stream().filter(elem -> !a1.contains(elem)).collect(Collectors.toList());
Ответ 7
Я думаю, вы говорите о С#. Если это так, вы можете попробовать это
ArrayList CompareArrayList(ArrayList a, ArrayList b)
{
ArrayList output = new ArrayList();
for (int i = 0; i < a.Count; i++)
{
string str = (string)a[i];
if (!b.Contains(str))
{
if(!output.Contains(str)) // check for dupes
output.Add(str);
}
}
return output;
}
Ответ 8
Вы просто сравниваете строки.
Поместите значения в ArrayList A как ключи в HashTable A.
Поместите значения в ArrayList B как ключи в HashTable B.
Затем для каждой клавиши в HashTable A удалите ее из HashTable B, если она существует.
В HashTable B вы остались строки (ключи), которые не были значениями в ArrayList A.
Пример С# (3.0), добавленный в ответ на запрос для кода:
List<string> listA = new List<string>{"2009-05-18","2009-05-19","2009-05-21'"};
List<string> listB = new List<string>{"2009-05-18","2009-05-18","2009-05-19","2009-05-19","2009-05-20","2009-05-21","2009-05-21","2009-05-22"};
HashSet<string> hashA = new HashSet<string>();
HashSet<string> hashB = new HashSet<string>();
foreach (string dateStrA in listA) hashA.Add(dateStrA);
foreach (string dateStrB in listB) hashB.Add(dateStrB);
foreach (string dateStrA in hashA)
{
if (hashB.Contains(dateStrA)) hashB.Remove(dateStrA);
}
List<string> result = hashB.ToList<string>();
Ответ 9
Привет, используйте этот класс, это сравнит оба списка и отобразит точно несоответствие двух списков.
import java.util.ArrayList;
import java.util.List;
public class ListCompare {
/**
* @param args
*/
public static void main(String[] args) {
List<String> dbVinList;
dbVinList = new ArrayList<String>();
List<String> ediVinList;
ediVinList = new ArrayList<String>();
dbVinList.add("A");
dbVinList.add("B");
dbVinList.add("C");
dbVinList.add("D");
ediVinList.add("A");
ediVinList.add("C");
ediVinList.add("E");
ediVinList.add("F");
/*ediVinList.add("G");
ediVinList.add("H");
ediVinList.add("I");
ediVinList.add("J");*/
List<String> dbVinListClone = dbVinList;
List<String> ediVinListClone = ediVinList;
boolean flag;
String mismatchVins = null;
if(dbVinListClone.containsAll(ediVinListClone)){
flag = dbVinListClone.removeAll(ediVinListClone);
if(flag){
mismatchVins = getMismatchVins(dbVinListClone);
}
}else{
flag = ediVinListClone.removeAll(dbVinListClone);
if(flag){
mismatchVins = getMismatchVins(ediVinListClone);
}
}
if(mismatchVins != null){
System.out.println("mismatch vins : "+mismatchVins);
}
}
private static String getMismatchVins(List<String> mismatchList){
StringBuilder mismatchVins = new StringBuilder();
int i = 0;
for(String mismatch : mismatchList){
i++;
if(i < mismatchList.size() && i!=5){
mismatchVins.append(mismatch).append(",");
}else{
mismatchVins.append(mismatch);
}
if(i==5){
break;
}
}
String mismatch1;
if(mismatchVins.length() > 100){
mismatch1 = mismatchVins.substring(0, 99);
}else{
mismatch1 = mismatchVins.toString();
}
return mismatch1;
}
}
Ответ 10
ЭТА РАБОТА ТАКЖЕ С Arraylist
// Create a couple ArrayList objects and populate them
// with some delicious fruits.
ArrayList<String> firstList = new ArrayList<String>() {/**
*
*/
private static final long serialVersionUID = 1L;
{
add("apple");
add("orange");
add("pea");
}};
ArrayList<String> secondList = new ArrayList<String>() {
/**
*
*/
private static final long serialVersionUID = 1L;
{
add("apple");
add("orange");
add("banana");
add("strawberry");
}};
// Show the "before" lists
System.out.println("First List: " + firstList);
System.out.println("Second List: " + secondList);
// Remove all elements in firstList from secondList
secondList.removeAll(firstList);
// Show the "after" list
System.out.println("Result: " + secondList);