ฉันต้องการกรองjava.util.Collection
ตามกริยา
ฉันต้องการกรองjava.util.Collection
ตามกริยา
คำตอบ:
Java 8 ( 2014 ) แก้ปัญหานี้โดยใช้สตรีมและ lambdas ในโค้ดหนึ่งบรรทัด:
List<Person> beerDrinkers = persons.stream()
.filter(p -> p.getAge() > 16).collect(Collectors.toList());
ใช้Collection#removeIf
เพื่อปรับเปลี่ยนคอลเลกชันในสถานที่ (หมายเหตุ: ในกรณีนี้เพรดิเคตจะลบออบเจกต์ที่ตอบสนองเพรดิเคต):
persons.removeIf(p -> p.getAge() <= 16);
lambdajอนุญาตการกรองคอลเลกชันโดยไม่ต้องเขียนลูปหรือคลาสภายใน:
List<Person> beerDrinkers = select(persons, having(on(Person.class).getAge(),
greaterThan(16)));
คุณลองนึกภาพสิ่งที่อ่านง่ายขึ้นได้ไหม
ข้อจำกัดความรับผิดชอบ:ฉันเป็นผู้สนับสนุนใน lambdaj
persons.removeIf(p -> p.getAge() <= 16);
สมมติว่าคุณใช้Java 1.5และคุณไม่สามารถเพิ่มGoogle Collectionsฉันจะทำสิ่งที่คล้ายกับที่ Google ทำ นี่เป็นความแตกต่างเล็กน้อยในความคิดเห็นของจอน
เพิ่มอินเทอร์เฟซนี้ไปยัง codebase ของคุณก่อน
public interface IPredicate<T> { boolean apply(T type); }
ผู้ใช้งานสามารถตอบเมื่อภาคแสดงบางอย่างเป็นจริงของบางประเภท เช่นถ้าT
มีUser
และAuthorizedUserPredicate<User>
ดำเนินการIPredicate<T>
แล้วAuthorizedUserPredicate#apply
ผลตอบแทนที่ไม่ว่าจะผ่านUser
ได้รับอนุญาต
จากนั้นในคลาสยูทิลิตี้บางอย่างคุณสามารถพูดได้
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;
}
ดังนั้นสมมติว่าคุณมีการใช้งานด้านบนอาจจะเป็น
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);
หากประสิทธิภาพในการตรวจสอบแบบเชิงเส้นมีความกังวลฉันอาจต้องการมีวัตถุโดเมนที่มีการรวบรวมเป้าหมาย วัตถุโดเมนที่มีการรวบรวมเป้าหมายจะมีการกรองตรรกะสำหรับวิธีการที่เริ่มต้นเพิ่มและตั้งค่าการเก็บรวบรวมเป้าหมาย
UPDATE:
ในคลาสยูทิลิตี้ (สมมุติว่าเพรดิเคต) ฉันได้เพิ่มเมธอด select พร้อมตัวเลือกสำหรับค่าเริ่มต้นเมื่อเพรดิเคตไม่ส่งคืนค่าที่คาดไว้และยังเป็นคุณสมบัติคงที่สำหรับ params ที่จะใช้ภายใน 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;
}
}
ตัวอย่างต่อไปนี้ค้นหาวัตถุที่หายไประหว่างคอลเลกชัน:
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;
}
});
ตัวอย่างต่อไปนี้ค้นหาอินสแตนซ์ในคอลเลกชันและส่งกลับองค์ประกอบแรกของคอลเลกชันเป็นค่าเริ่มต้นเมื่อไม่พบอินสแตนซ์:
MyType myObject = Predicate.select(collectionOfMyType, new IPredicate<MyType>() {
public boolean apply(MyType objectOfMyType) {
return objectOfMyType.isDefault();
}}, collectionOfMyType.get(0));
อัปเดต (หลังจากรีลีส Java 8):
เป็นเวลาหลายปีแล้วที่ฉัน (อลัน) โพสต์คำตอบนี้เป็นครั้งแรกและฉันก็ยังไม่เชื่อว่าฉันกำลังรวบรวมคะแนน SO สำหรับคำตอบนี้ ไม่ว่าอย่างไรก็ตาม ณ ขณะนี้ที่ Java 8 ได้แนะนำการปิดภาษาคำตอบของฉันตอนนี้จะแตกต่างกันมากและง่ายขึ้น ด้วย Java 8 ไม่จำเป็นต้องมีคลาสยูทิลิตี้สแตติกที่แตกต่างกัน ดังนั้นหากคุณต้องการค้นหาองค์ประกอบที่ 1 ที่ตรงกับภาคแสดงของคุณ
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 สำหรับ optionals มีความสามารถในการget()
, isPresent()
, orElse(defaultUser)
, orElseGet(userSupplier)
และorElseThrow(exceptionSupplier)
เช่นเดียวกับคนอื่น ๆ 'เอก' ฟังก์ชั่นเช่นmap
, และflatMap
filter
หากคุณต้องการรวบรวมผู้ใช้ทั้งหมดที่ตรงกับเพรดิเคตนั้นให้ใช้Collectors
เพื่อยุติการสตรีมในการรวบรวมที่ต้องการ
final UserService userService = ... // perhaps injected IoC
final List<UserModel> userOption = userCollection.stream().filter(u -> {
boolean isAuthorized = userService.isAuthorized(u);
return isAuthorized;
}).collect(Collectors.toList());
ดูที่นี่สำหรับตัวอย่างเพิ่มเติมเกี่ยวกับการทำงานของสตรีม Java 8
val authorized = for (user <- users if user.isAuthorized) yield user
ใช้CollectionUtils.filter (Collection, Predicate)จาก Apache Commons
วิธีที่ "ดีที่สุด" เป็นการร้องขอที่กว้างเกินไป มันเป็น "สั้น" หรือไม่? "เร็วที่สุด"? "อ่าน"? กรองในสถานที่หรือในคอลเลกชันอื่นหรือไม่
วิธีที่ง่ายที่สุด (แต่ไม่สามารถอ่านได้มากที่สุด) คือทำซ้ำและใช้เมธอด Iterator.remove ():
Iterator<Foo> it = col.iterator();
while( it.hasNext() ) {
Foo foo = it.next();
if( !condition(foo) ) it.remove();
}
ตอนนี้เพื่อให้สามารถอ่านได้มากขึ้นคุณสามารถห่อมันเป็นวิธีการยูทิลิตี้ จากนั้นคิดค้นอินเทอร์เฟซ IPredicate สร้างการใช้งานที่ไม่ระบุชื่อของอินเทอร์เฟซนั้นและทำสิ่งที่ชอบ:
CollectionUtils.filterInPlace(col,
new IPredicate<Foo>(){
public boolean keepIt(Foo foo) {
return foo.isBar();
}
});
โดยที่ filterInPlace () วนซ้ำคอลเล็กชันและเรียกใช้ Predicate.keepIt () เพื่อเรียนรู้ว่าอินสแตนซ์ที่จะเก็บไว้ในคอลเล็กชัน
ฉันไม่เห็นเหตุผลในการนำห้องสมุดบุคคลที่สามมาใช้สำหรับงานนี้
stream()
มีฟีเจอร์ แต่ทุกคนจะไม่เล่นกับของเล่นใหม่ล่าสุด: P
พิจารณาGoogle Collectionsสำหรับเฟรมเวิร์กคอลเล็กชันที่อัปเดตซึ่งรองรับ generics
อัปเดต : ห้องสมุด google collection เลิกใช้แล้ว คุณควรใช้Guavaรุ่นล่าสุดแทน มันยังคงมีนามสกุลเดียวกันทั้งหมดในเฟรมเวิร์กคอลเล็กชันรวมถึงกลไกการกรองตามเพรดิเคต
รอ 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());
personList.removeIf(p -> p.age < 30);
verbose น้อยลง นอกจากนี้ฉันเคยได้ยินพูดคุยเกี่ยวกับการเริ่มใช้ apis ที่ยอมรับและส่งคืนStream
s แทนCollection
s เพราะStream
มีประโยชน์มากและรวดเร็ว แต่การไป / จากพวกเขาช้า
ตั้งแต่การเปิดตัว Java 8 รุ่นแรกคุณสามารถลองสิ่งต่อไปนี้:
Collection<T> collection = ...;
Stream<T> stream = collection.stream().filter(...);
ตัวอย่างเช่นหากคุณมีรายการจำนวนเต็มและคุณต้องการกรองตัวเลขที่> 10 แล้วพิมพ์ตัวเลขเหล่านั้นไปที่คอนโซลคุณสามารถทำสิ่งต่อไปนี้:
List<Integer> numbers = Arrays.asList(12, 74, 5, 8, 16);
numbers.stream().filter(n -> n > 10).forEach(System.out::println);
ฉันจะโยนRxJavaในวงแหวนซึ่งมีให้ในAndroidด้วย RxJava อาจไม่ใช่ตัวเลือกที่ดีที่สุดเสมอไป แต่มันจะช่วยให้คุณมีความยืดหยุ่นมากขึ้นถ้าคุณต้องการเพิ่มการแปลงเพิ่มเติมในคอลเลกชันของคุณหรือจัดการข้อผิดพลาดขณะกรอง
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);
}
});
เอาท์พุท:
1
3
5
การตั้งค่า:
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();
}
}
}
การใช้งาน:
List<MyObject> myList = ...;
filterCollection(myList, new Predicate<MyObject>() {
public boolean filter(MyObject obj) {
return obj.shouldFilter();
}
});
เกี่ยวกับ Java ธรรมดาและ straighforward บางตัว
List<Customer> list ...;
List<Customer> newList = new ArrayList<>();
for (Customer c : list){
if (c.getName().equals("dd")) newList.add(c);
}
ง่ายอ่านง่ายและใช้งานได้บน Android! แต่ถ้าคุณใช้ Java 8 คุณสามารถทำได้ด้วยบรรทัดเดียว:
List<Customer> newList = list.stream().filter(c -> c.getName().equals("dd")).collect(toList());
โปรดทราบว่า toList () จะถูกนำเข้าแบบคงที่
คุณแน่ใจหรือไม่ว่าต้องการกรองชุดสะสมเองแทนที่จะเป็นตัววนซ้ำ
ดูorg.apache.commons.collections.iterators.FilterIterator
หรือใช้เวอร์ชัน 4 ของ apache คอมมอนส์org.apache.commons.collections4.iterators.FilterIterator
ดู Let 's ที่วิธีการกรองในตัว JDK รายการและMutableListใช้Eclipse คอลเลกชัน
List<Integer> jdkList = Arrays.asList(1, 2, 3, 4, 5);
MutableList<Integer> ecList = Lists.mutable.with(1, 2, 3, 4, 5);
หากคุณต้องการกรองตัวเลขน้อยกว่า 3 คุณคาดหวังผลลัพธ์ต่อไปนี้
List<Integer> selected = Lists.mutable.with(1, 2);
List<Integer> rejected = Lists.mutable.with(3, 4, 5);
นี่คือวิธีที่คุณสามารถกรองโดยใช้ Java 8 Predicate
แลมบ์ดาเป็น
Assert.assertEquals(selected, Iterate.select(jdkList, each -> each < 3));
Assert.assertEquals(rejected, Iterate.reject(jdkList, each -> each < 3));
Assert.assertEquals(selected, ecList.select(each -> each < 3));
Assert.assertEquals(rejected, ecList.reject(each -> each < 3));
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));
นี่คือทางเลือกอื่นในการกรองรายการ JDK และEclipse Collections MutableLists โดยใช้โรงงานPredicates
Assert.assertEquals(selected, Iterate.select(jdkList, Predicates.lessThan(3)));
Assert.assertEquals(selected, ecList.select(Predicates.lessThan(3)));
นี่เป็นรุ่นที่ไม่ได้จัดสรรวัตถุสำหรับการวินิจฉัยโดยใช้Predicates2โรงงานแทนกับวิธีการที่ใช้selectWith
Predicate2
Assert.assertEquals(
selected, ecList.selectWith(Predicates2.<Integer>lessThan(), 3));
บางครั้งคุณต้องการกรองตามเงื่อนไขเชิงลบ reject
มีวิธีการพิเศษในการคราสคอลเลกชันที่เรียกว่าเป็น
Assert.assertEquals(rejected, Iterate.reject(jdkList, lessThan3));
Assert.assertEquals(rejected, ecList.reject(lessThan3));
วิธีการที่จะกลับมาสองคอลเลกชันที่มีองค์ประกอบที่เลือกโดยและปฏิเสธโดยpartition
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());
หมายเหตุ: ฉันเป็นคอมมิชชันสำหรับ Eclipse Collections
removeIf
ในรายการหรือตั้งค่าสำหรับดั้งเดิม?
ด้วย ForEach DSL คุณสามารถเขียนได้
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();
ได้รับชุดของ [The, quick, brown, fox, jumps, over, the, lazy, dog] ผลลัพธ์เป็น [quick, brown, jumps, over, lazy] นั่นคือสตริงทั้งหมดยาวกว่าสามอักขระ
รูปแบบการวนซ้ำทั้งหมดที่รองรับโดย ForEach DSL คือ
AllSatisfy
AnySatisfy
Collect
Counnt
CutPieces
Detect
GroupedBy
IndexOf
InjectInto
Reject
Select
สำหรับรายละเอียดเพิ่มเติมโปรดดูที่https://www.iam.unibe.ch/scg/svn_repos/Sources/ForEach
วิธีCollections2.filter (Collection, Predicate)ในห้องสมุด Guava ของ Googleทำในสิ่งที่คุณต้องการ
ตั้งแต่เปิดใช้งานจาวา 9 Collectors.filtering
:
public static <T, A, R>
Collector<T, ?, R> filtering(Predicate<? super T> predicate,
Collector<? super T, A, R> downstream)
ดังนั้นการกรองควรจะ:
collection.stream().collect(Collectors.filtering(predicate, collector))
ตัวอย่าง:
List<Integer> oddNumbers = List.of(1, 19, 15, 10, -10).stream()
.collect(Collectors.filtering(i -> i % 2 == 1, Collectors.toList()));
เมื่อรวมกับการขาดการปิดจริง ๆ แล้วสิ่งนี้เป็นสิ่งที่จับต้องได้มากที่สุดสำหรับ Java จริงๆแล้ววิธีการต่าง ๆ ที่กล่าวมาข้างต้นนั้นค่อนข้างง่ายต่อการอ่านและมีประสิทธิภาพจริงๆ อย่างไรก็ตามหลังจากใช้เวลากับ. Net, Erlang และอื่น ๆ ... ความเข้าใจในรายการรวมเข้ากับระดับภาษาทำให้ทุกอย่างสะอาดขึ้น หากไม่มีการเพิ่มเติมในระดับภาษาจาวาก็คงไม่สะอาดเท่ากับภาษาอื่น ๆ ในพื้นที่นี้
หากประสิทธิภาพเป็นสิ่งที่น่ากังวลอย่างมากคอลเล็กชันของ Google คือหนทางที่จะไป ไวยากรณ์ของแลมบ์ดาสามารถอ่านได้มากขึ้นสำหรับบางคน แต่ก็ไม่ค่อยมีประสิทธิภาพเท่าไหร่
แล้วมีห้องสมุดที่ฉันเขียน ฉันจะเพิกเฉยต่อคำถามใด ๆ เกี่ยวกับประสิทธิภาพของมัน (ใช่แล้วมันแย่มาก) ...... ใช่ฉันรู้ว่ามันมีการสะท้อนที่ชัดเจนและไม่มีฉันไม่ได้ใช้จริง ๆ แต่มันใช้งานได้:
LinkedList<Person> list = ......
LinkedList<Person> filtered =
Query.from(list).where(Condition.ensure("age", Op.GTE, 21));
หรือ
LinkedList<Person> list = ....
LinkedList<Person> filtered = Query.from(list).where("x => x.age >= 21");
JFilter http://code.google.com/p/jfilter/เหมาะสมที่สุดสำหรับความต้องการของคุณ
JFilter เป็นไลบรารี่โอเพนซอร์สที่ง่ายและมีประสิทธิภาพสูงในการสืบค้นคอลเลคชั่นของ Java beans
ฟีเจอร์หลัก
ฉันเขียนคลาส Iterable เพิ่มเติมที่สนับสนุนการใช้อัลกอริทึมการทำงานโดยไม่คัดลอกเนื้อหาคอลเลกชัน
การใช้งาน:
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);
}
รหัสข้างต้นจะทำงานจริง
for( int n : myList )
{
if( n % 2 == 0 )
{
System.out.println(n);
}
}
ใช้การเก็บแบบสอบถาม Engine (CQEngine) มันเป็นวิธีที่เร็วที่สุดในการทำสิ่งนี้
ดูเพิ่มเติม: คุณค้นหาคอลเลกชันวัตถุใน Java (Criteria / SQL-like) ได้อย่างไร?
บางคำตอบที่ยอดเยี่ยมจริงๆที่นี่ ฉันฉันต้องการที่จะรักษาความเรียบง่ายและอ่านง่ายที่สุดเท่าที่จะเป็นไปได้:
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();
}
}
}
}
}
โซลูชัน pre-Java8 ง่าย ๆ :
ArrayList<Item> filtered = new ArrayList<Item>();
for (Item item : items) if (condition(item)) filtered.add(item);
น่าเสียดายที่โซลูชันนี้ไม่ได้เป็นแบบทั่วไปอย่างสมบูรณ์ แต่ให้แสดงรายการมากกว่าประเภทของคอลเลกชันที่กำหนด นอกจากนี้การนำห้องสมุดหรือการเขียนฟังก์ชั่นที่ห่อรหัสนี้ดูเหมือนจะเกินความจริงของฉันเว้นแต่ว่าเงื่อนไขนั้นซับซ้อน แต่คุณสามารถเขียนฟังก์ชันสำหรับเงื่อนไขได้
https://code.google.com/p/joquery/
รองรับความเป็นไปได้ที่แตกต่างกัน
ให้สะสม
Collection<Dto> testList = new ArrayList<>();
ประเภท
class Dto
{
private int id;
private String text;
public int getId()
{
return id;
}
public int getText()
{
return text;
}
}
กรอง
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();
นอกจากนี้
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"});
การเรียงลำดับ (มีให้สำหรับ Java 7)
Filter<Dto> query = CQ.<Dto>filter(testList)
.orderBy()
.property(Dto::getId)
.property(Dto::getName)
Collection<Dto> sorted = query.list();
การจัดกลุ่ม (พร้อมใช้งานสำหรับ Java 7)
GroupQuery<Integer,Dto> query = CQ.<Dto,Dto>query(testList)
.group()
.groupBy(Dto::getId)
Collection<Grouping<Integer,Dto>> grouped = query.list();
ตัวเชื่อม (มีให้สำหรับ Java 7)
ป.ร. ให้ไว้
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<>();
สามารถเข้าร่วมได้เช่น
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();
การแสดงออก
Filter<Dto> query = CQ.<Dto>filter()
.from(testList)
.where()
.exec(s -> s.getId() + 1).eq().value(2);
คำตอบของฉันสร้างจากสิ่งนั้นจากเควินหว่องนี่เป็นหนึ่งซับในที่ใช้CollectionUtils
จากสปริงและนิพจน์แลมบ์ดาของ Java 8
CollectionUtils.filter(list, p -> ((Person) p).getAge() > 16);
นี่คือรัดกุมและสามารถอ่านได้เป็นทางเลือกอื่น ๆ ที่ฉันได้เห็น (โดยไม่ต้องใช้ห้องสมุดตามลักษณะ)
Spring CollectionUtilsมีให้ในรุ่นฤดูใบไม้ผลิ 4.0.2 ปล่อยและจำไว้ว่าคุณต้องมี JDK 1.8 และระดับภาษา 8+
การใช้โดยjava 8
เฉพาะlambda expression
คุณสามารถทำได้เช่นเดียวกับตัวอย่างด้านล่าง:
myProducts.stream().filter(prod -> prod.price>10).collect(Collectors.toList())
ที่สำหรับแต่ละคอลเลกชันproduct
ภายในmyProducts
ถ้าprod.price>10
จากนั้นเพิ่มผลิตภัณฑ์นี้ไปยังรายการกรองใหม่
ฉันต้องการกรองรายการตามค่าที่มีอยู่แล้วในรายการ ตัวอย่างเช่นลบค่าทั้งหมดตามที่น้อยกว่าค่าปัจจุบัน {2 5 3 4 7 5} -> {2 5 7} หรือตัวอย่างเช่นการลบรายการซ้ำทั้งหมด {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;
}
}
มันจะใช้ผึ้งแบบนี้
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;
}
});
ด้วยฝรั่ง:
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
ใน Java 8 คุณสามารถใช้วิธีการตัวกรองนี้โดยตรงแล้วทำเช่นนั้น
List<String> lines = Arrays.asList("java", "pramod", "example");
List<String> result = lines.stream()
.filter(line -> !"pramod".equals(line))
.collect(Collectors.toList());
result.forEach(System.out::println);