Czy są jakieś metody, aby to zrobić? Szukałem, ale nie mogłem znaleźć.
Kolejne pytanie: potrzebuję tych metod, aby móc filtrować pliki. Niektóre są AND
filtrami, a inne OR
filtrami (jak w teorii zbiorów), więc muszę filtrować według wszystkich plików i unite / intersects ArrayLists, które przechowują te pliki.
Czy powinienem używać innej struktury danych do przechowywania plików? Czy jest coś jeszcze, co zapewniłoby lepsze środowisko wykonawcze?
java
list
union
intersection
yotamoo
źródło
źródło
Vector
? Ta klasa jest odradzana od wersji Java 1.2.Vector
jest dla interakcji cross-wątku, ale są bezpieczniejsze struktury danych dla tych przypadkach używać zbyt. Zobacz także to pytanie .Vector
Moim zdaniem każda biblioteka, która nadal korzysta z 2016 roku, jest bardzo podejrzana.Odpowiedzi:
Oto prosta implementacja bez użycia biblioteki innej firmy. Główną zaletą nad
retainAll
,removeAll
iaddAll
to, że metody te nie zmieniają pierwotnego wejścia wykazy metod.public class Test { public static void main(String... args) throws Exception { List<String> list1 = new ArrayList<String>(Arrays.asList("A", "B", "C")); List<String> list2 = new ArrayList<String>(Arrays.asList("B", "C", "D", "E", "F")); System.out.println(new Test().intersection(list1, list2)); System.out.println(new Test().union(list1, list2)); } public <T> List<T> union(List<T> list1, List<T> list2) { Set<T> set = new HashSet<T>(); set.addAll(list1); set.addAll(list2); return new ArrayList<T>(set); } public <T> List<T> intersection(List<T> list1, List<T> list2) { List<T> list = new ArrayList<T>(); for (T t : list1) { if(list2.contains(t)) { list.add(t); } } return list; } }
źródło
HashSet
for,intersection
aby średnia wydajność przypadku wynosiła O (n) zamiast O (n ^ 2).Kolekcja (więc ArrayList również) ma:
col.retainAll(otherCol) // for intersection col.addAll(otherCol) // for union
Użyj implementacji List, jeśli akceptujesz powtórzenia, implementacji Set, jeśli nie:
Collection<String> col1 = new ArrayList<String>(); // {a, b, c} // Collection<String> col1 = new TreeSet<String>(); col1.add("a"); col1.add("b"); col1.add("c"); Collection<String> col2 = new ArrayList<String>(); // {b, c, d, e} // Collection<String> col2 = new TreeSet<String>(); col2.add("b"); col2.add("c"); col2.add("d"); col2.add("e"); col1.addAll(col2); System.out.println(col1); //output for ArrayList: [a, b, c, b, c, d, e] //output for TreeSet: [a, b, c, d, e]
źródło
HashSet
zamiast tego.addAll()
jest unia dla list; to po prostu konkatenacja drugiej listy na końcu pierwszej. Operacja sumująca pozwoli uniknąć dodania elementu, jeśli pierwsza lista już go zawiera.Ten post jest dość stary, ale mimo wszystko był to pierwszy, który pojawił się w Google podczas szukania tego tematu.
Chcę zaktualizować za pomocą strumieni Java 8, które (w zasadzie) robią to samo w jednym wierszu:
Jeśli ktoś ma lepsze / szybsze rozwiązanie to daj mi znać, ale to fajne rozwiązanie, które można łatwo włączyć do metody bez dodawania niepotrzebnej klasy / metody pomocniczej i nadal zachować czytelność.
źródło
Set
a następnie użyj metody zestawucontains
. Nie wszystko w życiu trzeba robić za pomocą strumieni.związek będzie
removeAll
i wtedyaddAll
.Znajdź więcej w dokumentacji kolekcji (ArrayList to zbiór) http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collection.html
źródło
retainAll()
iremoveAll()
są operacjami O (n ^ 2) na listach. Możemy zrobić lepiej.retainAll
z {1, 2, 2, 3, 4, 5} ponad {1, 2, 3} daje {1, 2, 2, 3}. Czy nie powinno to być {1, 2, 3} jako przecięcie?Związki i skrzyżowania zdefiniowane tylko dla zbiorów, a nie list. Jak wspomniałeś.
Sprawdź w bibliotece guawy filtry. Również guawa zapewnia prawdziwe skrzyżowania i połączenia
static <E> Sets.SetView<E >union(Set<? extends E> set1, Set<? extends E> set2) static <E> Sets.SetView<E> intersection(Set<E> set1, Set<?> set2)
źródło
Możesz użyć
CollectionUtils
z apache commons .źródło
Oznaczone rozwiązanie nie jest wydajne. Ma złożoność czasową O (n ^ 2). To, co możemy zrobić, to posortować obie listy i wykonać algorytm przecięcia, taki jak ten poniżej.
private static ArrayList<Integer> interesect(ArrayList<Integer> f, ArrayList<Integer> s) { ArrayList<Integer> res = new ArrayList<Integer>(); int i = 0, j = 0; while (i != f.size() && j != s.size()) { if (f.get(i) < s.get(j)) { i ++; } else if (f.get(i) > s.get(j)) { j ++; } else { res.add(f.get(i)); i ++; j ++; } } return res; }
Ten ma złożoność O (n log n + n), która jest równa O (n log n). Związek odbywa się w podobny sposób. Po prostu upewnij się, że dokonałeś odpowiednich modyfikacji w instrukcjach if-elseif-else.
Możesz także użyć iteratorów, jeśli chcesz (wiem, że są bardziej wydajne w C ++, nie wiem, czy tak jest również w Javie).
źródło
contains()
w pętli (jak sugeruje Devenv) zajęłoby O (n + m) czasu. Sortowanie jest niepotrzebnie skomplikowane i zajmuje O (n log n + m log n + n) czasu. To prawda, że czas skraca się do O (n log n), ale jest to wciąż gorsze niż czas liniowy i znacznie bardziej złożone.Myślę, że powinieneś użyć
Set
do przechowywania plików, jeśli chcesz zrobić na nich przecięcie i połączenie. Następnie można użyć Guava „s Zestawy klasa zrobićunion
,intersection
i filtrując przezPredicate
również. Różnica między tymi metodami a innymi sugestiami polega na tym, że wszystkie te metody tworzą leniwe widoki sumy, przecięcia itp. Dwóch zbiorów. Apache Commons tworzy nową kolekcję i kopiuje do niej dane.retainAll
zmienia jedną z twoich kolekcji, usuwając z niej elementy.źródło
Oto sposób, w jaki sposób można wykonać skrzyżowanie ze strumieniami (pamiętaj, że do strumieni musisz używać języka Java 8):
List<foo> fooList1 = new ArrayList<>(Arrays.asList(new foo(), new foo())); List<foo> fooList2 = new ArrayList<>(Arrays.asList(new foo(), new foo())); fooList1.stream().filter(f -> fooList2.contains(f)).collect(Collectors.toList());
Przykład list z różnymi typami. Jeśli masz związek między foo i bar i możesz uzyskać obiekt baru z foo, to możesz zmodyfikować swój strumień:
List<foo> fooList = new ArrayList<>(Arrays.asList(new foo(), new foo())); List<bar> barList = new ArrayList<>(Arrays.asList(new bar(), new bar())); fooList.stream().filter(f -> barList.contains(f.getBar()).collect(Collectors.toList());
źródło
Znalazłem ListUtils bardzo przydatne w tym przypadku użycia.
Użyj ListUtils z org.apache.commons.collections, jeśli nie chcesz modyfikować istniejącej listy.
ListUtils.intersection(list1, list2)
źródło
Możesz użyć commons-collections4 CollectionUtils
Collection<Integer> collection1 = Arrays.asList(1, 2, 4, 5, 7, 8); Collection<Integer> collection2 = Arrays.asList(2, 3, 4, 6, 8); Collection<Integer> intersection = CollectionUtils.intersection(collection1, collection2); System.out.println(intersection); // [2, 4, 8] Collection<Integer> union = CollectionUtils.union(collection1, collection2); System.out.println(union); // [1, 2, 3, 4, 5, 6, 7, 8] Collection<Integer> subtract = CollectionUtils.subtract(collection1, collection2); System.out.println(subtract); // [1, 5, 7]
źródło
W Javie 8 używam prostych metod pomocniczych, takich jak ta:
public static <T> Collection<T> getIntersection(Collection<T> coll1, Collection<T> coll2){ return Stream.concat(coll1.stream(), coll2.stream()) .filter(coll1::contains) .filter(coll2::contains) .collect(Collectors.toSet()); } public static <T> Collection<T> getMinus(Collection<T> coll1, Collection<T> coll2){ return coll1.stream().filter(not(coll2::contains)).collect(Collectors.toSet()); } public static <T> Predicate<T> not(Predicate<T> t) { return t.negate(); }
źródło
Jeśli obiekty na liście są hashable (tj. Mają przyzwoity hashCode i funkcję equals), najszybsze podejście między tabelami ok. size> 20 to skonstruowanie HashSet dla większej z dwóch list.
public static <T> ArrayList<T> intersection(Collection<T> a, Collection<T> b) { if (b.size() > a.size()) { return intersection(b, a); } else { if (b.size() > 20 && !(a instanceof HashSet)) { a = new HashSet(a); } ArrayList<T> result = new ArrayList(); for (T objb : b) { if (a.contains(objb)) { result.add(objb); } } return result; } }
źródło
Ja też pracowałem nad podobną sytuacją i dotarłem tutaj w poszukiwaniu pomocy. Skończyło się na znalezieniu własnego rozwiązania dla tablic. ArrayList AbsentDates = new ArrayList (); // Przechowuje Array1-Array2
Uwaga: opublikowanie tego, jeśli może to pomóc komuś dotrzeć do tej strony w celu uzyskania pomocy.
ArrayList<String> AbsentDates = new ArrayList<String>();//This Array will store difference public void AbsentDays() { findDates("April", "2017");//Array one with dates in Month April 2017 findPresentDays();//Array two carrying some dates which are subset of Dates in Month April 2017 for (int i = 0; i < Dates.size(); i++) { for (int j = 0; j < PresentDates.size(); j++) { if (Dates.get(i).equals(PresentDates.get(j))) { Dates.remove(i); } } AbsentDates = Dates; } System.out.println(AbsentDates ); }
źródło
Przecięcie dwóch list różnych obiektów opartych na wspólnym kluczu - Java 8
private List<User> intersection(List<User> users, List<OtherUser> list) { return list.stream() .flatMap(OtherUser -> users.stream() .filter(user -> user.getId() .equalsIgnoreCase(OtherUser.getId()))) .collect(Collectors.toList()); }
źródło
public static <T> Set<T> intersectCollections(Collection<T> col1, Collection<T> col2) { Set<T> set1, set2; if (col1 instanceof Set) { set1 = (Set) col1; } else { set1 = new HashSet<>(col1); } if (col2 instanceof Set) { set2 = (Set) col2; } else { set2 = new HashSet<>(col2); } Set<T> intersection = new HashSet<>(Math.min(set1.size(), set2.size())); for (T t : set1) { if (set2.contains(t)) { intersection.add(t); } } return intersection; }
JDK8 + (prawdopodobnie najlepsza wydajność)
public static <T> Set<T> intersectCollections(Collection<T> col1, Collection<T> col2) { boolean isCol1Larger = col1.size() > col2.size(); Set<T> largerSet; Collection<T> smallerCol; if (isCol1Larger) { if (col1 instanceof Set) { largerSet = (Set<T>) col1; } else { largerSet = new HashSet<>(col1); } smallerCol = col2; } else { if (col2 instanceof Set) { largerSet = (Set<T>) col2; } else { largerSet = new HashSet<>(col2); } smallerCol = col1; } return smallerCol.stream() .filter(largerSet::contains) .collect(Collectors.toSet()); }
Jeśli nie zależy Ci na wydajności i wolisz mniejszy kod, po prostu użyj:
źródło
One-liners od wersji Java 8
Suma, jeśli nie ma duplikatów:
return concat(a.stream(), b.stream()).collect(toList());
Unia i odrębne:
return concat(a.stream(), b.stream()).distinct().collect(toList());
Suma i odrębne, jeśli typ zwrotu kolekcji / zestawu:
return concat(a.stream(), b.stream()).collect(toSet());
Przetnij, jeśli nie ma duplikatów:
return a.stream().filter(b::contains).collect(toList());
Jeśli zbiór
b
jest duży i nie ma O (1), zoptymalizuj wstępnie działanie filtra, dodając 1 wiersz wcześniejreturn
. Skopiuj doHasSet
(import java.util.Set;
) :Przecinają się i wyróżniają:
return a.stream().distinct().filter(b::contains).collect(toList());
źródło
Ostateczne rozwiązanie:
//all sorted items from both public <T> List<T> getListReunion(List<T> list1, List<T> list2) { Set<T> set = new HashSet<T>(); set.addAll(list1); set.addAll(list2); return new ArrayList<T>(set); } //common items from both public <T> List<T> getListIntersection(List<T> list1, List<T> list2) { list1.retainAll(list2); return list1; } //common items from list1 not present in list2 public <T> List<T> getListDifference(List<T> list1, List<T> list2) { list1.removeAll(list2); return list1; }
źródło
Najpierw kopiuję wszystkie wartości tablic do jednej tablicy, a następnie usuwam zduplikowane wartości z tablicy. Linia 12, wyjaśniająca, czy ta sama liczba występuje dłużej niż czas, a następnie umieść dodatkową wartość śmieci w pozycji „j”. Na koniec przejdź od początku do końca i sprawdź, czy występuje ta sama wartość śmieci, a następnie odrzuć.
public class Union { public static void main(String[] args){ int arr1[]={1,3,3,2,4,2,3,3,5,2,1,99}; int arr2[]={1,3,2,1,3,2,4,6,3,4}; int arr3[]=new int[arr1.length+arr2.length]; for(int i=0;i<arr1.length;i++) arr3[i]=arr1[i]; for(int i=0;i<arr2.length;i++) arr3[arr1.length+i]=arr2[i]; System.out.println(Arrays.toString(arr3)); for(int i=0;i<arr3.length;i++) { for(int j=i+1;j<arr3.length;j++) { if(arr3[i]==arr3[j]) arr3[j]=99999999; //line 12 } } for(int i=0;i<arr3.length;i++) { if(arr3[i]!=99999999) System.out.print(arr3[i]+" "); } } }
źródło
ArrayList
do przechowywania wyniku unii.Integer
zamiastint
. Wtedy możesz użyćnull
zamiast swojej „wartości śmieciowej”. „Wartości śmieci” lub „wartości wartowników” są zwykle złym pomysłem, ponieważ te wartości mogą nadal występować w danych wejściowych.Po przeprowadzeniu testów, oto moje najlepsze podejście do skrzyżowania.
Większa prędkość w porównaniu do czystego podejścia HashSet. Poniższe HashSet i HashMap mają podobną wydajność dla tablic z ponad 1 milionem rekordów.
Jeśli chodzi o podejście Java 8 Stream, szybkość jest dość niska dla wielkości tablicy większej niż 10 KB.
Mam nadzieję, że to pomoże.
public static List<String> hashMapIntersection(List<String> target, List<String> support) { List<String> r = new ArrayList<String>(); Map<String, Integer> map = new HashMap<String, Integer>(); for (String s : support) { map.put(s, 0); } for (String s : target) { if (map.containsKey(s)) { r.add(s); } } return r; } public static List<String> hashSetIntersection(List<String> a, List<String> b) { Long start = System.currentTimeMillis(); List<String> r = new ArrayList<String>(); Set<String> set = new HashSet<String>(b); for (String s : a) { if (set.contains(s)) { r.add(s); } } print("intersection:" + r.size() + "-" + String.valueOf(System.currentTimeMillis() - start)); return r; } public static void union(List<String> a, List<String> b) { Long start = System.currentTimeMillis(); Set<String> r= new HashSet<String>(a); r.addAll(b); print("union:" + r.size() + "-" + String.valueOf(System.currentTimeMillis() - start)); }
źródło
retainAll () użycie metody do znalezienia wspólnego elementu..ie; intersection list1.retainAll (list2)
źródło
Możesz użyć metod:
CollectionUtils.containsAny
iCollectionUtils.containsAll
z Apache Commons .
źródło
Gdybyś miał swoje dane w Setach, mógłbyś użyć
Sets
klasy Guavy .źródło
Jeśli liczba pasuje, to sprawdzam, pojawia się za pierwszym razem lub nie przy pomocy "indexOf ()", jeśli liczba pasuje za pierwszym razem, wydrukuj i zapisz w ciągu, aby następnym razem pasowała ta sama liczba, wygrywa ' t print, ponieważ ze względu na warunek „indexOf ()” będzie fałszywy.
class Intersection { public static void main(String[] args) { String s=""; int[] array1 = {1, 2, 5, 5, 8, 9, 7,2,3512451,4,4,5 ,10}; int[] array2 = {1, 0, 6, 15, 6, 5,4, 1,7, 0,5,4,5,2,3,8,5,3512451}; for (int i = 0; i < array1.length; i++) { for (int j = 0; j < array2.length; j++) { char c=(char)(array1[i]); if(array1[i] == (array2[j])&&s.indexOf(c)==-1) { System.out.println("Common element is : "+(array1[i])); s+=c; } } } }
}
źródło