Jaki jest najlepszy sposób filtrowania kolekcji Java?

Chcę filtrować java.util.Collection Na podstawie predykatu.

Author: user2864740, 2008-09-23

26 answers

Java 8 (2014) rozwiązuje ten problem używając strumieni i lambda w jednej linii kodu:

List<Person> beerDrinkers = persons.stream()
    .filter(p -> p.getAge() > 16).collect(Collectors.toList());

Oto tutorial .

Użycie Collection#removeIf aby zmodyfikować kolekcję w miejscu. (Uwaga: w tym przypadku predykat usunie obiekty, które spełniają predykat):

persons.removeIf(p -> p.getAge() <= 16);

Lambdaj umożliwia filtrowanie kolekcji bez pisania pętli lub klas wewnętrznych:

List<Person> beerDrinkers = select(persons, having(on(Person.class).getAge(),
    greaterThan(16)));
Czy możesz sobie wyobrazić coś więcej czytelne?

Od 2006 roku jest członkiem Stowarzyszenia lambdaj.]}

 554
Author: Mario Fusco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-20 19:23:48

Zakładając, że używasz Java 1.5 i że nie możesz dodać kolekcji Google , zrobiłbym coś bardzo podobnego do tego, co zrobili faceci z Google. Jest to niewielka różnica w komentarzach Jona.

Najpierw dodaj ten interfejs do swojej bazy kodowej.

public interface IPredicate<T> { boolean apply(T type); }

Jego implementatorzy mogą odpowiedzieć, gdy określony predykat jest prawdziwy określonego typu. Np. Jeśli T były User i AuthorizedUserPredicate<User> implementują IPredicate<T>, to AuthorizedUserPredicate#apply zwraca czy przekazywana w User jest autoryzowany.

Wtedy w jakiejś klasie użytkowej, można powiedzieć

public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
    Collection<T> result = new ArrayList<T>();
    for (T element: target) {
        if (predicate.apply(element)) {
            result.add(element);
        }
    }
    return result;
}

Więc, zakładając, że masz zastosowanie powyższego może być

Predicate<User> isAuthorized = new Predicate<User>() {
    public boolean apply(User user) {
        // binds a boolean method in User to a reference
        return user.isAuthorized();
    }
};
// allUsers is a Collection<User>
Collection<User> authorizedUsers = filter(allUsers, isAuthorized);

Jeśli wydajność na sprawdzeniu liniowym jest niepokojąca, to mogę chcieć mieć obiekt domain, który ma kolekcję docelową. Obiekt domain, który ma kolekcję docelową, ma logikę filtrowania dla metod inicjalizujących, dodających i ustawiających kolekcję docelową.

Aktualizacja:

W klasie użytkowej (powiedzmy Predykat), dodałem metodę select z opcją wartości domyślnej, gdy predykat nie zwraca wartości oczekiwanej, a także statyczną właściwość dla params, które mają być używane wewnątrz nowego IPredicate.

public class Predicate {
    public static Object predicateParams;

    public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
        Collection<T> result = new ArrayList<T>();
        for (T element : target) {
            if (predicate.apply(element)) {
                result.add(element);
            }
        }
        return result;
    }

    public static <T> T select(Collection<T> target, IPredicate<T> predicate) {
        T result = null;
        for (T element : target) {
            if (!predicate.apply(element))
                continue;
            result = element;
            break;
        }
        return result;
    }

    public static <T> T select(Collection<T> target, IPredicate<T> predicate, T defaultValue) {
        T result = defaultValue;
        for (T element : target) {
            if (!predicate.apply(element))
                continue;
            result = element;
            break;
        }
        return result;
    }
}

Poniższy przykład szuka brakujących obiektów między kolekcjami:

List<MyTypeA> missingObjects = (List<MyTypeA>) Predicate.filter(myCollectionOfA,
    new IPredicate<MyTypeA>() {
        public boolean apply(MyTypeA objectOfA) {
            Predicate.predicateParams = objectOfA.getName();
            return Predicate.select(myCollectionB, new IPredicate<MyTypeB>() {
                public boolean apply(MyTypeB objectOfB) {
                    return objectOfB.getName().equals(Predicate.predicateParams.toString());
                }
            }) == null;
        }
    });

Poniższy przykład wyszukuje instancję w kolekcji i zwraca pierwszy element kolekcji jako wartość domyślną, gdy instancja nie zostanie znaleziona:

MyType myObject = Predicate.select(collectionOfMyType, new IPredicate<MyType>() {
public boolean apply(MyType objectOfMyType) {
    return objectOfMyType.isDefault();
}}, collectionOfMyType.get(0));

UPDATE (po wydaniu Javy 8):

Minęło kilka lat, odkąd (Alan) po raz pierwszy opublikował tę odpowiedź, i nadal nie mogę uwierzyć, że zbieram więc punkty za tę odpowiedź. W każdym razie, teraz, gdy Java 8 wprowadziła zamknięcia do języka, moja odpowiedź byłaby teraz znacznie inna i prostsza. W Javie 8 nie ma potrzeby stosowania odrębnej statycznej klasy narzędzi. Więc jeśli chcesz znaleźć pierwszy element, który pasuje do twojego predykatu.

final UserService userService = ... // perhaps injected IoC
final Optional<UserModel> userOption = userCollection.stream().filter(u -> {
    boolean isAuthorized = userService.isAuthorized(u);
    return isAuthorized;
}).findFirst();

JDK 8 API dla opcji ma zdolność do get(), isPresent(), orElse(defaultUser), orElseGet(userSupplier) i orElseThrow(exceptionSupplier), a także inne funkcje "monadyczne", takie jak map, flatMap i filter.

Jeśli chcesz po prostu zebrać wszystkich użytkowników, którzy pasują do predykatu, użyj Collectors, aby zakończyć strumień w żądanej kolekcji.

final UserService userService = ... // perhaps injected IoC
final List<UserModel> userOption = userCollection.stream().filter(u -> {
    boolean isAuthorized = userService.isAuthorized(u);
    return isAuthorized;
}).collect(Collectors.toList());

Zobacz tutaj aby uzyskać więcej przykładów działania strumieni Java 8.

 215
Author: Alan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-11 16:09:52
 87
Author: Kevin Wong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-17 06:11:33

"najlepszy" sposób to zbyt szeroka Prośba. Czy jest "najkrótsza"? "Najszybszy"? "Czytelny"? Filtrować w miejscu czy w innej kolekcji?

Najprostszym (ale nie najbardziej czytelnym) sposobem jest iteracja i użycie iteratora.metoda remove ():

Iterator<Foo> it = col.iterator();
while( it.hasNext() ) {
  Foo foo = it.next();
  if( !condition(foo) ) it.remove();
}

Teraz, aby uczynić go bardziej czytelnym, możesz owinąć go w metodę użytkową. Następnie wymyśl interfejs IPredicate, stwórz anonimową implementację tego interfejsu i zrób coś w stylu:

CollectionUtils.filterInPlace(col,
  new IPredicate<Foo>(){
    public boolean keepIt(Foo foo) {
      return foo.isBar();
    }
  });

Gdzie filterInPlace() iteruje kolekcję i wywołuje Predykat.keepIt (), aby dowiedzieć się, czy instancja ma być przechowywana w kolekcji.

Naprawdę nie widzę uzasadnienia dla sprowadzenia trzeciej biblioteki tylko do tego zadania.

 60
Author: Vladimir Dyuzhev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-17 16:26:29

Rozważ zbiory Google dla zaktualizowanego frameworka kolekcji, który obsługuje generyki.

Aktualizacja : biblioteka zbiorów google jest obecnie przestarzała. Zamiast tego należy użyć najnowszej wersji Guava. Nadal ma wszystkie te same rozszerzenia do frameworku kolekcji, w tym mechanizm filtrowania na podstawie predykatu.

 60
Author: Heath Borders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-13 19:26:35

Wait for Java 8:

List<Person> olderThan30 = 
  //Create a Stream from the personList
  personList.stream().
  //filter the element to select only those with age >= 30
  filter(p -> p.age >= 30).
  //put those filtered elements into a new List.
  collect(Collectors.toList());
 23
Author: gavenkoa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-24 08:24:01

Od wczesnej wersji Javy 8 można spróbować czegoś takiego:

Collection<T> collection = ...;
Stream<T> stream = collection.stream().filter(...);

Na przykład, jeśli masz listę liczb całkowitych i chcesz filtrować liczby, które są > 10, a następnie wydrukować te liczby do konsoli, możesz zrobić coś takiego:

List<Integer> numbers = Arrays.asList(12, 74, 5, 8, 16);
numbers.stream().filter(n -> n > 10).forEach(System.out::println);
 10
Author: Josh M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-27 21:41:55

Wrzucę RxJava do ringu, który jest również dostępny na Android . RxJava może nie zawsze być najlepszą opcją, ale daje większą elastyczność, jeśli chcesz dodać więcej przekształceń do swojej kolekcji lub obsłużyć błędy podczas filtrowania.

Observable.from(Arrays.asList(1, 2, 3, 4, 5))
    .filter(new Func1<Integer, Boolean>() {
        public Boolean call(Integer i) {
            return i % 2 != 0;
        }
    })
    .subscribe(new Action1<Integer>() {
        public void call(Integer i) {
            System.out.println(i);
        }
    });

Wyjście:

1
3
5

Więcej szczegółów na temat RxJava ' s filter można znaleźć tutaj .

 9
Author: anon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-14 23:25:12

Konfiguracja:

public interface Predicate<T> {
  public boolean filter(T t);
}

void filterCollection(Collection<T> col, Predicate<T> predicate) {
  for (Iterator i = col.iterator(); i.hasNext();) {
    T obj = i.next();
    if (predicate.filter(obj)) {
      i.remove();
    }
  }
}

Użycie:

List<MyObject> myList = ...;
filterCollection(myList, new Predicate<MyObject>() {
  public boolean filter(MyObject obj) {
    return obj.shouldFilter();
  }
});
 6
Author: jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 16:41:27

A może jakaś prosta i prosta Java

 List<Customer> list ...;
 List<Customer> newList = new ArrayList<>();
 for (Customer c : list){
    if (c.getName().equals("dd")) newList.add(c);
 }

Prosty, czytelny i łatwy (i działa w Androidzie!) Ale jeśli używasz Javy 8 możesz to zrobić w słodkiej jednej linijce:

List<Customer> newList = list.stream().filter(c -> c.getName().equals("dd")).collect(toList());

Zauważ, że tolist () jest importowane statycznie

 6
Author: Nestor Hernandez Loli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-12 05:03:57

Czy na pewno chcesz filtrować samą kolekcję, a nie iterator?

Zobacz org.Apacz.commons.Kolekcje.Iteratory.FilterIterator

Lub używając wersji 4 Apache commons org.Apacz.commons.kolekcje4.Iteratory.FilterIterator

 6
Author: ykaganovich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-16 08:43:33

Przyjrzyjmy się jak filtrować wbudowaną listę JDK i MutableList używając kolekcji Eclipse (dawniej kolekcji GS).

List<Integer> jdkList = Arrays.asList(1, 2, 3, 4, 5);
MutableList<Integer> ecList = Lists.mutable.with(1, 2, 3, 4, 5);

Jeśli chcesz filtrować liczby mniejsze niż 3, spodziewaj się następujących wyników.

List<Integer> selected = Lists.mutable.with(1, 2);
List<Integer> rejected = Lists.mutable.with(3, 4, 5);

Oto jak możesz filtrować używając anonimowej klasy wewnętrznej jako Predicate.

Predicate<Integer> lessThan3 = new Predicate<Integer>()
{
    public boolean accept(Integer each)
    {
        return each < 3;
    }
};

Assert.assertEquals(selected, Iterate.select(jdkList, lessThan3));

Assert.assertEquals(selected, ecList.select(lessThan3));

Oto kilka alternatyw dla filtrowania list JDK i kolekcji Eclipse MutableLists za pomocą predykaty fabryka.

Assert.assertEquals(selected, Iterate.select(jdkList, Predicates.lessThan(3)));

Assert.assertEquals(selected, ecList.select(Predicates.lessThan(3)));

Oto wersja, która nie przydziela obiektu dla predykatu, używając fabryki predykatów Predykaty2 zamiast metody selectWith, która przyjmuje Predicate2.

Assert.assertEquals(
    selected, ecList.selectWith(Predicates2.<Integer>lessThan(), 3));

Czasami chcesz filtrować pod negatywnym warunkiem. W zbiorach Eclipse istnieje specjalna metoda o nazwie reject.

Assert.assertEquals(rejected, Iterate.reject(jdkList, lessThan3));

Assert.assertEquals(rejected, ecList.reject(lessThan3));

Oto jak można filtrować używając Java 8 lambda jako Predicate.

Assert.assertEquals(selected, Iterate.select(jdkList, each -> each < 3));
Assert.assertEquals(rejected, Iterate.reject(jdkList, each -> each < 3));

Assert.assertEquals(selected, gscList.select(each -> each < 3));
Assert.assertEquals(rejected, gscList.reject(each -> each < 3));

Metoda partition zwróci dwa zbiory, zawierające elementy wybrane i odrzucone przez Predicate.

PartitionIterable<Integer> jdkPartitioned = Iterate.partition(jdkList, lessThan3);
Assert.assertEquals(selected, jdkPartitioned.getSelected());
Assert.assertEquals(rejected, jdkPartitioned.getRejected());

PartitionList<Integer> ecPartitioned = gscList.partition(lessThan3);
Assert.assertEquals(selected, ecPartitioned.getSelected());
Assert.assertEquals(rejected, ecPartitioned.getRejected());

Uwaga: jestem committerem Dla Kolekcji Eclipse.

 5
Author: Donald Raab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-08 04:20:22

Z ForEach DSL możesz napisać

import static ch.akuhn.util.query.Query.select;
import static ch.akuhn.util.query.Query.$result;
import ch.akuhn.util.query.Select;

Collection<String> collection = ...

for (Select<String> each : select(collection)) {
    each.yield = each.value.length() > 3;
}

Collection<String> result = $result();

Biorąc pod uwagę zbiór [the, quick, brown, fox, jumps, over, the, lazy, dog], skutkuje to [quick, brown, jumps, over, lazy], czyli wszystkimi ciągami dłuższymi niż trzy znaki.

Wszystkie style iteracji obsługiwane przez ForEach DSL are

  • AllSatisfy
  • AnySatisfy
  • Collect
  • Counnt
  • CutPieces
  • Detect
  • GroupedBy
  • IndexOf
  • InjectInto
  • Reject
  • Select

Aby uzyskać więcej informacji, zapoznaj się z https://www.iam.unibe.ch/scg/svn_repos/Sources/ForEach

 4
Author: akuhn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-03 16:20:21
 4
Author: Kevin Wong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-09 21:19:44

To, w połączeniu z brakiem prawdziwych zamknięć, jest moim największym zmartwieniem dla Javy. Szczerze mówiąc, większość wymienionych powyżej metod jest dość łatwa do odczytania i naprawdę skuteczna; jednak po spędzeniu czasu z. Net, Erlang itp... zrozumienie listy zintegrowane na poziomie językowym sprawia, że wszystko jest o wiele czystsze. Bez dodatków na poziomie języka Java nie może być tak czysta, jak wiele innych języków w tej dziedzinie.

Jeśli wydajność jest ogromnym problemem, zbiory Google to sposób aby przejść (lub napisać własne proste narzędzie predykatu). Składnia Lambdaj jest dla niektórych bardziej czytelna, ale nie jest tak wydajna.

I jest jeszcze biblioteka, którą napisałem. Zignoruję wszelkie pytania dotyczące jego skuteczności(tak, jest tak źle)...... Tak, Wiem, że jest wyraźnie odbity i nie, nie używam go, ale działa: {]}

LinkedList<Person> list = ......
LinkedList<Person> filtered = 
           Query.from(list).where(Condition.ensure("age", Op.GTE, 21));

Lub

LinkedList<Person> list = ....
LinkedList<Person> filtered = Query.from(list).where("x => x.age >= 21");
 3
Author: jdc0589,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-23 03:55:48

JFilter http://code.google.com/p/jfilter / najlepiej odpowiada Twoim wymaganiom.

JFilter jest prostą i wydajną biblioteką open source do odpytywania kolekcji Java beans.

Kluczowe cechy

  • Wsparcie kolekcji (java.util.Kolekcja, java.util.Map i Array) właściwości.
  • Wsparcie zbioru wewnątrz zbioru o dowolnej głębokości.
  • Wsparcie zapytań wewnętrznych.
  • Wsparcie parametryzowanych zapytań.
  • Can filter 1 milion rekordów w kilka 100 ms.
  • Filter (query) jest podany w prostym formacie json, jest jak zapytania Mangodb. Oto kilka przykładów.
  • {"id": {"$le": "10"}
    • gdzie właściwość object id jest mniejsza niż równa 10.
  • {"id": {"$in": ["0", " 100"]}}
    • gdzie właściwość object id wynosi 0 lub 100.
  • {"lineItems": {"lineAmount": "1"}}
    • gdzie właściwość kolekcji lineItems typu parametryzowanego ma wartość lineAmount równą 1.
  • {"$and":[{"id": "0"}, {"billingAddress":{"city": "DEL"}}]}
    • gdzie właściwość id wynosi 0 i billingAddress.właścicielem miasta jest DEL.
  • {"lineItems": {"taxes": {"key": {"code": "GST"}, "value": {"$gt": "1.01"}}}}
    • gdzie właściwość kolekcji lineItems parametryzowanego typu, która ma właściwość map type parametryzowanego typu, ma kod równy wartości GST większej niż 1.01.
  • {"$or": [{"code": "10"}, {"SKU": {"$i": [{"cena": {"$w':['20', '40']}}, {'Kod": "RedApple"}]}}]}
    • Wybierz wszystkie produkty, w których Kod produktu to 10 lub cena sku w 20 i 40, A kod sku to "RedApple".
 2
Author: Kamran Ali Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-05 10:46:58

Napisałem rozszerzoną klasę Iterable, która wspiera stosowanie algorytmów funkcjonalnych bez kopiowania zawartości kolekcji.

Użycie:

List<Integer> myList = new ArrayList<Integer>(){ 1, 2, 3, 4, 5 }

Iterable<Integer> filtered = Iterable.wrap(myList).select(new Predicate1<Integer>()
{
    public Boolean call(Integer n) throws FunctionalException
    {
        return n % 2 == 0;
    }
})

for( int n : filtered )
{
    System.out.println(n);
}

Powyższy kod faktycznie wykona

for( int n : myList )
{
    if( n % 2 == 0 ) 
    {
        System.out.println(n);
    }
}
 2
Author: Vincent Robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-23 15:50:02

Use Collection Query Engine (CQEngine). Jest to zdecydowanie najszybszy sposób, aby to zrobić.

Zobacz także: Jak odpytywać zbiory obiektów w Javie (Criteria/SQL-like)?

 2
Author: npgall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:25

Od java 9 Collectors.filtering jest włączone:

public static <T, A, R>
    Collector<T, ?, R> filtering(Predicate<? super T> predicate,
                                 Collector<? super T, A, R> downstream)

Zatem filtrowanie powinno być:

collection.stream().collect(Collectors.filtering(predicate, collector))

Przykład:

List<Integer> oddNumbers = List.of(1, 19, 15, 10, -10).stream()
            .collect(Collectors.filtering(i -> i % 2 == 1, Collectors.toList()));
 2
Author: fbokovikov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-24 13:59:00

Proste rozwiązanie pre-Java8:

ArrayList<Item> filtered = new ArrayList<Item>(); 
for (Item item : items) if (condition(item)) filtered.add(item);

Niestety to rozwiązanie nie jest w pełni ogólne, wypisując listę, a nie Typ danej kolekcji. Ponadto wprowadzanie bibliotek lub pisanie funkcji zawijających ten kod wydaje mi się przesadą, chyba że warunek jest złożony, ale wtedy możesz napisać funkcję dla warunku.

 1
Author: Andrew McKnight,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-03 19:15:32

Https://code.google.com/p/joquery/

Obsługuje różne możliwości,

Dany zbiór,

Collection<Dto> testList = new ArrayList<>();

Typu,

class Dto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

Filtr

Java 7

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property("id").eq().value(1);
Collection<Dto> filtered = query.list();

Java 8

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property(Dto::getId)
    .eq().value(1);
Collection<Dto> filtered = query.list();

Również,

Filter<Dto> query = CQ.<Dto>filter()
        .from(testList)
        .where()
        .property(Dto::getId).between().value(1).value(2)
        .and()
        .property(Dto::grtText).in().value(new string[]{"a","b"});

Sortowanie (dostępne również dla Java 7)

Filter<Dto> query = CQ.<Dto>filter(testList)
        .orderBy()
        .property(Dto::getId)
        .property(Dto::getName)
    Collection<Dto> sorted = query.list();

Grupowanie (dostępne również dla Javy 7)

GroupQuery<Integer,Dto> query = CQ.<Dto,Dto>query(testList)
        .group()
        .groupBy(Dto::getId)
    Collection<Grouping<Integer,Dto>> grouped = query.list();

Joins (dostępny również dla Java 7)

Podane,

class LeftDto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

class RightDto
{
    private int id;
    private int leftId;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getLeftId()
        {
            return leftId;
        }

    public int getText()
    {
        return text;
    }
}

class JoinedDto
{
    private int leftId;
    private int rightId;
    private String text;

    public JoinedDto(int leftId,int rightId,String text)
    {
        this.leftId = leftId;
        this.rightId = rightId;
        this.text = text;
    }

    public int getLeftId()
    {
        return leftId;
    }

    public int getRightId()
        {
            return rightId;
        }

    public int getText()
    {
        return text;
    }
}

Collection<LeftDto> leftList = new ArrayList<>();

Collection<RightDto> rightList = new ArrayList<>();

Można połączyć tak,

Collection<JoinedDto> results = CQ.<LeftDto, LeftDto>query().from(leftList)
                .<RightDto, JoinedDto>innerJoin(CQ.<RightDto, RightDto>query().from(rightList))
                .on(LeftFyo::getId, RightDto::getLeftId)
                .transformDirect(selection ->  new JoinedDto(selection.getLeft().getText()
                                                     , selection.getLeft().getId()
                                                     , selection.getRight().getId())
                                 )
                .list();

Wyrażenia

Filter<Dto> query = CQ.<Dto>filter()
    .from(testList)
    .where()
    .exec(s -> s.getId() + 1).eq().value(2);
 1
Author: Low Flying Pelican,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-03 12:59:35

Moja odpowiedź opiera się na tym od Kevina Wonga, tutaj jako jednolinijkowy za pomocą CollectionUtils z spring i wyrażenia Java 8 lambda.

CollectionUtils.filter(list, p -> ((Person) p).getAge() > 16);

Jest to tak zwięzłe i czytelne, jak każda alternatywa, jaką widziałem (bez użycia bibliotek opartych na aspektach)

Spring CollectionUtils jest dostępny od wersji wiosennej 4.0.2.Wydaj i pamiętaj, że potrzebujesz JDK 1.8 i poziomu językowego 8+.

 1
Author: vikingsteve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-22 11:18:24

Kilka naprawdę świetnych, świetnych odpowiedzi tutaj. Ja bym chciał żeby było jak najbardziej proste i czytelne:

public abstract class AbstractFilter<T> {

    /**
     * Method that returns whether an item is to be included or not.
     * @param item an item from the given collection.
     * @return true if this item is to be included in the collection, false in case it has to be removed.
     */
    protected abstract boolean excludeItem(T item);

    public void filter(Collection<T> collection) {
        if (CollectionUtils.isNotEmpty(collection)) {
            Iterator<T> iterator = collection.iterator();
            while (iterator.hasNext()) {
                if (excludeItem(iterator.next())) {
                    iterator.remove();
                }
            }
        }
    }
}
 1
Author: Lawrence,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-05 16:22:48

Używając java 8, a konkretnie lambda expression, możesz to zrobić po prostu jak w poniższym przykładzie:

myProducts.stream().filter(prod -> prod.price>10).collect(Collectors.toList())

Gdzie dla każdej product wewnątrz myProducts kolekcji, Jeśli prod.price>10, to dodaj ten produkt do nowej listy filtrowanej.

 0
Author: hd84335,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-12 21:47:55

Z Guawą:

Collection<Integer> collection = Lists.newArrayList(1, 2, 3, 4, 5);

Iterators.removeIf(collection.iterator(), new Predicate<Integer>() {
    @Override
    public boolean apply(Integer i) {
        return i % 2 == 0;
    }
});

System.out.println(collection); // Prints 1, 3, 5
 0
Author: ZhekaKozlov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-15 09:26:44

Musiałem filtrować listę w zależności od wartości już obecnych na liście. Na przykład usuń wszystkie następujące wartości, które są mniejsze niż bieżąca wartość. {2 5 3 4 7 5} -> {2 5 7}. Lub na przykład, aby usunąć wszystkie duplikaty {3 5 4 2 3 5 6} -> {3 5 4 2 6}.

public class Filter {
    public static <T> void List(List<T> list, Chooser<T> chooser) {
        List<Integer> toBeRemoved = new ArrayList<>();
        leftloop:
        for (int right = 1; right < list.size(); ++right) {
            for (int left = 0; left < right; ++left) {
                if (toBeRemoved.contains(left)) {
                    continue;
                }
                Keep keep = chooser.choose(list.get(left), list.get(right));
                switch (keep) {
                    case LEFT:
                        toBeRemoved.add(right);
                        continue leftloop;
                    case RIGHT:
                        toBeRemoved.add(left);
                        break;
                    case NONE:
                        toBeRemoved.add(left);
                        toBeRemoved.add(right);
                        continue leftloop;
                }
            }
        }

        Collections.sort(toBeRemoved, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

        for (int i : toBeRemoved) {
            if (i >= 0 && i < list.size()) {
                list.remove(i);
            }
        }
    }

    public static <T> void List(List<T> list, Keeper<T> keeper) {
        Iterator<T> iterator = list.iterator();
        while (iterator.hasNext()) {
            if (!keeper.keep(iterator.next())) {
                iterator.remove();
            }
        }
    }

    public interface Keeper<E> {
        boolean keep(E obj);
    }

    public interface Chooser<E> {
        Keep choose(E left, E right);
    }

    public enum Keep {
        LEFT, RIGHT, BOTH, NONE;
    }
}

To będzie używane w ten sposób.

List<String> names = new ArrayList<>();
names.add("Anders");
names.add("Stefan");
names.add("Anders");
Filter.List(names, new Filter.Chooser<String>() {
    @Override
    public Filter.Keep choose(String left, String right) {
        return left.equals(right) ? Filter.Keep.LEFT : Filter.Keep.BOTH;
    }
});
 0
Author: Fredrik Metcalf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-15 14:28:05