জাভা সংগ্রহ ফিল্টার করার সেরা উপায় কী?


উত্তর:


698

জাভা 8 ( 2014 ) কোডের এক লাইনে স্ট্রিম এবং ল্যাম্বডাস ব্যবহার করে এই সমস্যাটি সমাধান করে:

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

এখানে একটি টিউটোরিয়াল

Collection#removeIfজায়গায় জায়গায় সংগ্রহটি পরিবর্তন করতে ব্যবহার করুন । (বিজ্ঞপ্তি: এক্ষেত্রে, প্রিডিটিক প্রাকটিকাকে সন্তুষ্টকারী বস্তুগুলি সরিয়ে ফেলবে):

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

ল্যাম্বডাজ লুপ বা অভ্যন্তরীণ ক্লাস না লিখে ফিল্টারিং সংগ্রহের অনুমতি দেয়:

List<Person> beerDrinkers = select(persons, having(on(Person.class).getAge(),
    greaterThan(16)));

আপনি কি আরও কিছু পঠনযোগ্য কল্পনা করতে পারেন?

দাবি অস্বীকার : আমি ল্যাম্বডাজের একজন সহযোগী


34
দুর্দান্ত তবে স্থিতিশীল আমদানি যা চলছে তা অবরুদ্ধ করে। রেফারেন্সের জন্য, ch.lambdaj.Lambda এ স্থিতিশীল আমদানি নির্বাচন করুন / রাখা / করুন হ'ল বৃহত্তর org.hamcrest.Matchers
মাইকপ্যাটেল

11
ল্যাম্বডজে সত্যিই সেক্সি, তবে এটি উল্লেখযোগ্য যে এটি একটি উল্লেখযোগ্য ওভারহেড (2.6 গড়) বোঝায় : কোড . google.com/p/lambdaj/wiki/P પ્રભાવ সম্পাদন অ্যানালাইসিস
ডক ড্যাভলুজ

7
: দৃশ্যত Android এর উপর কাজ করে না groups.google.com/forum/#!msg/lambdaj/km7uFgvSd3k/grJhgl3ik5sJ
মরটিজ

7
সত্যিই লামদাজের এই উদাহরণটি পছন্দ করুন ... লাম্বডা ফাংশনের সাথে অন্তর্নির্মিত নেট। এবং 16 বছর বয়সে একজন ব্যক্তি কোথায় পান করতে পারেন? আমাদের স্থানীয়করণের সীমাবদ্ধতাটি বিবেচনা করা উচিত। : পি
এমব্রাহাম 1

3
অপসারণের উদাহরণটি হওয়া উচিতpersons.removeIf(p -> p.getAge() <= 16);
vim

223

ধরে নিই যে আপনি জাভা 1.5 ব্যবহার করছেন এবং আপনি গুগল সংগ্রহগুলি যোগ করতে পারবেন না , আমি গুগল ছেলেরা যা করেছে তার সাথে আমি খুব অনুরূপ কিছু করব। এটি জনের মন্তব্যে সামান্য প্রকরণ।

প্রথমে আপনার ইন্টারফেসটি আপনার কোডবেসে যুক্ত করুন।

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);

লিনিয়ার চেকের পারফরম্যান্স যদি উদ্বেগের বিষয় হয় তবে আমি হয়ত এমন একটি ডোমেন অবজেক্ট রাখতে চাই যাতে লক্ষ্য সংগ্রহ রয়েছে। লক্ষ্য সংগ্রহ রয়েছে এমন ডোমেন অবজেক্টটিতে লক্ষ্য সংগ্রহ সংগ্রহের সূচনা, সংযোজন এবং সেট করার পদ্ধতিগুলির জন্য ফিল্টারিং লজিক থাকবে।

হালনাগাদ:

ইউটিলিটি ক্লাসে (আসুন প্রিডিকেট বলুন), যখন প্রাকটিকেট প্রত্যাশিত মানটি ফেরত না দেয় তখন আমি ডিফল্ট মানের বিকল্পের সাথে একটি নির্বাচন পদ্ধতি যুক্ত করেছি এবং নতুন আইপ্রেডিকেটের অভ্যন্তরে প্যারাম ব্যবহারের জন্য একটি স্থিতিশীল সম্পত্তিও রয়েছে।

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));

আপডেট (জাভা 8 প্রকাশের পরে):

আমি (অ্যালান) প্রথম এই উত্তরটি পোস্ট করার পরে বেশ কয়েক বছর হয়েছে এবং আমি এখনও বিশ্বাস করতে পারি না যে আমি এই উত্তরের জন্য এসও পয়েন্ট সংগ্রহ করছি। যে কোনও হারে, এখন জাভা 8 ভাষার কাছে ক্লোজার চালু করেছে, আমার উত্তরটি এখন বেশ আলাদা এবং সহজতর হবে। জাভা 8 এর সাথে আলাদা স্ট্যাটিক ইউটিলিটি ক্লাসের প্রয়োজন নেই। সুতরাং আপনি যদি 1 ম উপাদানটি খুঁজে পেতে চান যা আপনার প্রাকটিকেটের সাথে মেলে।

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

Optionals জন্য JDK 8 এপিআই ক্ষমতা আছে 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());

জাভা 8 স্ট্রিমগুলি কীভাবে কাজ করে তার আরও উদাহরণের জন্য এখানে দেখুন ।


27
হ্যাঁ, তবে আমি আবারও বারবার চাকাটিকে নতুন করে তুলতে ঘৃণা করি। আমি বরং কিছু ইউটিলিটি লাইব্রেরি খুঁজে পেতে চাই যা যখন আমি চাই
কেভিন ওং 18

2
আপনি যদি নতুন সংগ্রহটি না চান তবে এটি সর্বোত্তম উপায় নয়। ফিল্টার পুনরাবৃত্তকারী রূপক ব্যবহার করুন, যা কোনও নতুন সংগ্রহের সাথে ইনপুট করতে পারে বা এটি আপনার যা প্রয়োজন তা হতে পারে।
জোশ

@ নেস্টার: একটি স্কেল বোঝার মধ্যে, ফিল্টারিং অনেক সহজ হবে:val authorized = for (user <- users if user.isAuthorized) yield user
অ্যালান

এটি কি মূল সংগ্রহটি সংশোধন করে বা একেবারে নতুন তৈরি করে? আমি এই পদ্ধতিটি ব্যবহার করে চেষ্টা করেছি এবং আমার সংগ্রহগুলি দুটিই লগ করেছি (মূল এবং পদ্ধতিটি থেকে ফিরে আসা), সেগুলি একই। @ অ্যালান
রোহান

1
@ রোহান, এটি মূল সংগ্রহটি পরিবর্তিত করার উদ্দেশ্যে নয়। নোট করুন যে উপরের ফলাফল সংগ্রহটি সদ্য নির্মিত and
অ্যালান

92

অ্যাপাচি কমন্স থেকে কালেকশনUtils.filter (সংগ্রহ, পূর্বাভাস) ব্যবহার করুন ।


3
এটি ঠিক আছে, তবে এটি জেনেরিক নয় এবং স্থানটি সংগ্রহের পরিবর্তে (সুন্দর নয়)
কেভিন ওয়াং

2
কালেকশন ইউটিলে অন্যান্য ফিল্টার পদ্ধতি রয়েছে যা মূল সংগ্রহটি পরিবর্তন করে না।
skaffman

42
বিশেষত, পদ্ধতিটি যে জায়গায় সংগ্রহটি পরিবর্তিত করে না তা হ'ল org.apache.commons.collections. সংগ্রহ সংগ্রহসমূহ # নির্বাচন (সংগ্রহ, পূর্বাভাস)
ইরো

5
Commons সংগ্রহ v4 এ এটি এখন জেনারিক্স ব্যবহার করে।
জাস্টিন এমেরি

1
এই পদ্ধতিটি সাবধানতার সাথে ব্যবহার করা উচিত কারণ এটি পুনরায় নির্ভর করে (কমপক্ষে কমন্স-সংগ্রহ -৩.২.১ প্রয়োগের ক্ষেত্রে) পুনরুক্তিকারী.রেমোভ () পদ্ধতি যা সংগ্রহের জন্য optionচ্ছিক, তাই ফিল্টারিংয়ের পরিবর্তে, বলুন, একটি অ্যারে, আপনি সম্ভবত একটি অসমর্থিত অপারেশন ধারণাটি পান।
ব্যবহারকারী 2417480

67

"সেরা" উপায়টি খুব চওড়া একটি অনুরোধ। এটি কি "সংক্ষিপ্ততম"? "দ্রুততম"? "রিডেবল"? জায়গায় বা অন্য কোনও সংগ্রহে ফিল্টার করবেন?

সবচেয়ে সহজ (তবে সর্বাধিক পঠনযোগ্য নয়) উপায় হ'ল এটি পুনরাবৃত্তি করা এবং Iterator.remove () পদ্ধতিটি ব্যবহার করুন:

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

এখন, এটিকে আরও পঠনযোগ্য করার জন্য, আপনি এটি কোনও ইউটিলিটি পদ্ধতিতে মোড়ানো করতে পারেন। তারপরে একটি আইপ্রেডিকেট ইন্টারফেস আবিষ্কার করুন, সেই ইন্টারফেসটির একটি বেনামে বাস্তবায়ন তৈরি করুন এবং এর মতো কিছু করুন:

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

যেখানে ফিল্টারইনপ্লেস () সংগ্রহটি পুনরাবৃত্তি করে এবং উদাহরণটি সংগ্রহের মধ্যে রাখা আছে কিনা তা জানতে Predicate.keepIt () কে কল করে।

আমি কেবল এই কাজের জন্য একটি তৃতীয় পক্ষের লাইব্রেরি আনার পক্ষে যুক্তি দেখছি না।


6
আমার ভোট এইটির জন্য যায়: এটি কেবল কাজ করে, কোনও বাহ্যিক লাইব্রেরি ছাড়াই। আমি কখনই বুঝতে পারি নি যে কোনও আইট্রেটর ইনস্ট্যান্ট করা প্রকৃত পক্ষে প্রতিটি সিনট্যাক্স ব্যবহারের তুলনায় কার্যকর হতে পারে, বা আপনি কোনও তালিকা থেকে আইটেমগুলি কনকেনারমোডফিকেশনএক্সেপশন বা এর মতো কিছু বাদ দিতে পারেন। :)
জিরোওয়ে

1
আমি মনে করি এটি অনুলিপি ছাড়াই স্ট্যান্ডার্ড জাভা লিব ব্যবহারের সেরা উপায়। 1.8 এর জন্য stream()বৈশিষ্ট্যটি থাকবে তবে প্রত্যেকেরই নতুন খেলনা খেলতে পারা যায় না: পি
পপুলাস

এটি কি মূল সংগ্রহটিও পরিবর্তন করে? @ জিরোওন
রোহান

হ্যাঁ অবশ্যই তা করেন, @ রোহান। আপনি বিশ্বাস না হলে এটি চেষ্টা করুন। ;)
জিরোআন

হাহাহা! তবে আমি আমার মূল সংগ্রহটি ধরে রাখতে চাই। আপনি কি বাহ্যিক lib যোগ না করে এটি করার একটি উপায় প্রস্তাব করতে পারেন? @ জিরোওন
রোহান

62

জেনেরিক্স সমর্থন করে এমন একটি আপডেট সংগ্রহের কাঠামোর জন্য গুগল সংগ্রহগুলি বিবেচনা করুন

আপডেট : গুগল সংগ্রহের পাঠাগারটি এখন হ্রাস করা হয়েছে। পরিবর্তে আপনার পেয়ারার সাম্প্রতিক প্রকাশটি ব্যবহার করা উচিত । এটি কোনও সংগ্রহের উপর ভিত্তি করে ফিল্টারিংয়ের প্রক্রিয়া সহ সংগ্রহ কাঠামোতে এখনও একই একই এক্সটেনশান রয়েছে।


হ্যাঁ, আমি গুগল সংগ্রহগুলি সম্পর্কে জানতাম। আমি যে সংস্করণটি ব্যবহার করেছিলাম তার মধ্যে সংগ্রহ 2 নেই। আমি এই প্রশ্নের একটি নতুন উত্তর যুক্ত করেছি যা নির্দিষ্ট পদ্ধতির তালিকা করে।
কেভিন ওয়াং

7
কেভিন, Iterables.filter () এবং Iterators.filter () শুরু থেকেই সেখানে ছিলেন এবং সাধারণত আপনার যা প্রয়োজন তা হ'ল।
কেভিন বোউরিলিয়ন

28

জাভা 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());

13
উহ্ ... এটা খুব ভার্জোজ। কেন তারা কেবল এটি করতে পারেনি: <পার্সন> ফলাফল = তালিকা = ব্যক্তিলিস্ট.ফিল্টার (p -> p.age> 30);
কেভিন ওয়াং

8
সরাসরি ফিল্টার ব্যবহার করার জন্য সংগ্রহ আপনি ব্যবহার করার প্রয়োজন removeIf : কল download.java.net/jdk8/docs/api/java/util/...
gavenkoa

6
@ কেভিনওয়ং "ভার্বোজ" পুরোপুরি বর্ণনা করে যা আমি ভাবব। কমপক্ষে তারা কি ধারাবাহিক?
বিশৃঙ্খল

5
কেন কালেক্টর.টললিস্ট () শেষ অংশে ব্যবহার করবেন না?
নেস্টর হার্নান্দেজ ললি

3
এখানে একটি লিঙ্ক প্রদান করা gavenkoa যে 404. নেই personList.removeIf(p -> p.age < 30);কম বাগাড়ম্বরপূর্ণ। এছাড়াও, আমি এপিআইএস বাস্তবায়ন শুরু করার বিষয়ে কথা শুনেছি যা এসগুলির Streamচেয়ে গ্রহণযোগ্য এবং ফিরে আসায় Collectionকারণ Streamগুলি খুব দরকারী এবং দ্রুত কিন্তু সেগুলি থেকে / যাওয়া খুব ধীর।
ক্যাপ্টেন ম্যান

11

জাভা 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);

11

আমি আরক্সজাভাটিকে রিংয়ে ফেলে দেব যা অ্যান্ড্রয়েডেও উপলব্ধ । আরএক্সজাভা সর্বদা সেরা বিকল্প নাও হতে পারে তবে আপনি যদি আপনার সংগ্রহে আরও ট্রান্সফর্মেশন যুক্ত করতে চান বা ফিল্টারিংয়ের সময় ত্রুটিগুলি পরিচালনা করতে চান তবে এটি আপনাকে আরও নমনীয়তা দেবে।

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

আরএক্সজাভা সম্পর্কিত আরও বিশদ এখানেfilter পাওয়া যাবে


7

সেটআপ:

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();
  }
});

2
ভাল, তবে আমি অ্যালান বাস্তবায়ন পছন্দ করি কারণ আপনি সংগ্রহটি পরিবর্তন করার পরিবর্তে একটি অনুলিপি পান। তদুপরি, অ্যালানের কোড থ্রেড নিরাপদ যখন আপনার নেই।
মার্কোস্পেরিরা

7

কিভাবে কিছু সরল এবং সোজা জাভা সম্পর্কে

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

সরল, পঠনযোগ্য এবং সহজ (এবং অ্যান্ড্রয়েডে কাজ করে!) তবে আপনি জাভা 8 ব্যবহার করলে আপনি এটি একটি মিষ্টির লাইনে করতে পারেন:

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

নোট করুন যে টোললিস্ট () স্থিতিশীলভাবে আমদানিকৃত



7

আসুন দেখে নেওয়া যাক কীভাবে অন্তর্নির্মিত জেডিকে তালিকা এবং এক্লিপস সংগ্রহগুলি ব্যবহার করে একটি মিউটেবললিস্ট ফিল্টার করবেন ।

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);

আপনি জাভা 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));

ভবিষ্যদ্বাণী কারখানাটি ব্যবহার করে জেডিকে তালিকাগুলি এবং এক্লিপস সংগ্রহগুলি মিউটেবললিস্টগুলি ফিল্টার করার জন্য এখানে কিছু বিকল্প রয়েছে ।

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

এখানে এমন একটি সংস্করণ রয়েছে যা প্রিডিকেটস 2 কারখানাটি ব্যবহার করে পরিবর্তিত selectWithপদ্ধতিটির পরিবর্তে প্রিডিকেটস 2 কারখানাটি ব্যবহার করে প্রাকটিকের জন্য কোনও বস্তু বরাদ্দ করে না 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());

দ্রষ্টব্য: আমি গ্রহগ্রাহ সংগ্রহের প্রতিশ্রুতিবদ্ধ।


1
আপনি কীভাবে removeIfকোনও তালিকায় একটি কাজ করবেন বা আদিমদের জন্য সেট করবেন?
বিবেক রাও

অপসারণের আইপিআইটি ইসি 9.1 সালে আদিম সংগ্রহগুলিতে যুক্ত করা হয়েছিল। eclipse.org/collections/javadoc/9.1.0/org/eclipse/collections/…
ডোনাল্ড রাব

5

ফোরিচ ডিএসএল দিয়ে আপনি লিখতে পারেন

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();

[দ্য, কুইক, ব্রাউন, শিয়াল, লাফানো, ওভার, দ্য, অলস, কুকুর) এর একটি সংকলন দেওয়া হয়েছে যার ফলে [দ্রুত, বাদামী, লাফানো, ওভার, অলস] অর্থাত্ সমস্ত স্ট্রিং তিনটি অক্ষরের চেয়ে দীর্ঘ।

ফোরিচ ডিএসএল সমর্থিত সমস্ত পুনরাবৃত্ত শৈলীগুলি

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

আরও তথ্যের জন্য, দয়া করে https://www.iam.unibe.ch/scg/svn_repos/Source/ ForEach দেখুন


বেশ চতুর! যদিও একটি দুর্দান্ত রুবি-ইশ সিনট্যাক্স বাস্তবায়নের জন্য প্রচুর কাজ! নেতিবাচক হ'ল আপনার ফিল্টারটি প্রথম শ্রেণির ফাংশন নয় এবং তাই এটি পুনরায় ব্যবহার করা যাবে না।
ক্লোজারগুলিতে

ভাল যুক্তি. লুপের বডিটি পুনরায় ব্যবহার করার একটি উপায় হ'ল পদ্ধতিটিকে লুপটিকে পুনরায় ব্যবহার করা হয় যা নির্বাচনের ক্যোয়ারিকে প্যারামিটার হিসাবে গ্রহণ করে। এটি অবশ্য এখনও আসল বন্ধের মতো কার্যকর এবং শক্তিশালী নয়, এটি অবশ্যই।
akuhn


5

যেহেতু জাভা 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()));

3

এটি আসল বন্ধের অভাবের সাথে মিলিত, এটি জাভার জন্য আমার সবচেয়ে বড় গ্রিপ। সত্যি বলতে, উপরে উল্লিখিত বেশিরভাগ পদ্ধতিগুলি পড়া সহজ এবং খুব দক্ষ; যাইহোক, নেট, এরলং ইত্যাদির সাথে সময় ব্যয় করার পরে ... ভাষা স্তরে সংহত তালিকা বোধগম্যতা সবকিছুকে আরও পরিষ্কার করে তোলে। ভাষা স্তরে সংযোজন ছাড়া জাভা এই অঞ্চলে অন্যান্য অনেক ভাষার মতোই পরিষ্কার হতে পারে না।

যদি কর্মক্ষমতা একটি বিশাল উদ্বেগ হয় তবে গুগল সংগ্রহগুলি হ'ল উপায় (বা আপনার নিজস্ব সহজ প্রাক্কলিত ইউটিলিটি লিখুন)। ল্যাম্বডাজ সিনট্যাক্স কিছু লোকের পক্ষে আরও পঠনযোগ্য তবে এটি যথেষ্ট দক্ষ নয়।

এবং তারপরে আমার লেখা একটি গ্রন্থাগার রয়েছে। আমি এর দক্ষতা (হ্যাঁ, এটি যে খারাপ) সম্পর্কে কোনও প্রশ্ন উপেক্ষা করব ...... হ্যাঁ, আমি এর স্পষ্ট প্রতিফলন ভিত্তিক জানি, এবং না আমি আসলে এটি ব্যবহার করি না, তবে এটি কাজ করে:

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");

লিঙ্ক করবেন? এমনকি আপনার গ্রন্থাগারটি অকার্যকর বা অন্যথায় অব্যবহৃত হলেও উত্স উপলব্ধ কিনা তা দেখার জন্য এটি আকর্ষণীয় হতে পারে।
ম্যাট্রিক্সফ্রোগ

রেপোটিকে সর্বজনীনভাবে তৈরি করেছেন ( নেট- ম্যাচাইন . com / সিনেফেরো / পি / জেডক্লিব / সোর্স / ট্র্রি / মাস্টার )। আপনি এক্সপ্রেশন প্যাকেজ আগ্রহী। পরীক্ষার প্যাকেজটিতে পরীক্ষামূলক উদাহরণ রয়েছে। উপরে বর্ণিত স্ট্রিং ক্যোয়ারী ইন্টারফেসটিতে আমি সত্যিই খুব বেশি কাজ করতে পারি নি (সত্যিকারের পার্সার লেখার মতো মনে হয় নি), সুতরাং পরীক্ষকের স্পষ্টত ক্যোয়ারী ইন্টারফেসটি যাওয়ার উপায়।
jdc0589

2

জেফিল্টার http://code.google.com/p/jfilter/ আপনার প্রয়োজনের জন্য সবচেয়ে উপযুক্ত।

জেফিল্টার জাভা মটরশুটি সংগ্রহের জন্য ক্যোয়ারী করার জন্য একটি সহজ এবং উচ্চতর পারফরম্যান্সের ওপেন সোর্স লাইব্রেরি।

মূল বৈশিষ্ট্য

  • সংগ্রহের সহায়তা (java.util. Colલેક્શન, java.util.Map এবং অ্যারে) বৈশিষ্ট্য।
  • যে কোনও গভীরতার সংগ্রহের অভ্যন্তরে সংগ্রহের সহায়তা।
  • অভ্যন্তরীণ প্রশ্নের সহায়তা।
  • প্যারামিটারাইজড কোয়েরিগুলির সমর্থন।
  • কয়েকটি 100 এমএসে 1 মিলিয়ন রেকর্ড ফিল্টার করতে পারে।
  • ফিল্টার (ক্যোরি) সাধারণ জসন ফর্ম্যাটে দেওয়া হয়, এটি ম্যাংডব ক্যোয়ারির মতো। নীচে কয়েকটি উদাহরণ দেওয়া হল।
  • {"আইডি": {"$ লে": "10"}
    • যেখানে অবজেক্ট আইডি সম্পত্তি 10 এর সমান কম।
  • {"আইডি": {"$ ইন": ["0", "100"]}
    • যেখানে অবজেক্ট আইডি সম্পত্তি 0 বা 100।
  • { "লাইনআইটেমগুলি": { "lineAmount": "1"}}
    • যেখানে প্যারামিটারাইজড ধরণের লাইন আইটেম সংগ্রহের সম্পত্তিটির লাইনঅ্যামাউন্ট 1 সমান হয়।
  • {"$ এবং": [{"আইডি": "0"}, {"বিলিং অ্যাড্রেস": city "শহর": "দেল"}}]}
    • যেখানে আইডি সম্পত্তি 0 এবং বিলিংএড্রেস.সিটি সম্পত্তি হ'ল দেল।
  • line "লাইন আইটেম": taxes "কর": key "কী": {"কোড": "জিএসটি"}, "মান": {"$ জিটি": "1.01"}}}}
    • যেখানে প্যারামিটারাইজড প্রকারের ম্যাপের ধরণের সম্পত্তি রয়েছে এমন প্যারামিটারাইজড ধরণের লাইন আইটেম সংগ্রহের সংস্থার কোডের মূল্য 1.01 এর চেয়ে বেশি জিএসটি মানের সমান।
  • {'$ বা': [{'কোড': '10'}, {'স্কাস': {'$ এবং': [{'দাম': {'$ in': ['20', '40']} }, {'কোড': 'রেড অ্যাপল'}]}}]}
    • সমস্ত পণ্য নির্বাচন করুন যেখানে পণ্যের কোড 10 বা স্কু দাম 20 এবং 40 তে হয় এবং স্কু কোডটি "রেড অ্যাপল"।

1
আপনার দাবি অস্বীকার করা উচিত যে আপনি লেখক (যেমনটি আমি মনে করি এটি কেস)।
assylias

হ্যাঁ, আমি এই গ্রন্থাগারের লেখক।
কামরান আলী খান

2

আমি একটি বর্ধিত আইটেবল ক্লাস লিখেছি যা সংগ্রহের সামগ্রীটি অনুলিপি না করে ফাংশনাল অ্যালগরিদম প্রয়োগ করতে সহায়তা করে।

ব্যবহার:

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);
    }
}

2

2

কিছু সত্যিই দুর্দান্ত দুর্দান্ত উত্তর এখানে। আমি, আমি পাতলা যতটা সম্ভব সহজ এবং পঠনযোগ্য রাখতে চাই:

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

সহজ প্রাক জাভা 8 সমাধান:

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

দুর্ভাগ্যক্রমে এই সমাধানটি সম্পূর্ণ জেনারিক নয়, প্রদত্ত সংগ্রহের ধরণের চেয়ে একটি তালিকা আউটপুট করে। এছাড়াও, লাইব্রেরি আনতে বা এই কোডটি মোড়ানো ফাংশনগুলি লেখার বিষয়টি শর্তটি জটিল না হলে আমার কাছে ওভারকিলের মতো বলে মনে হয় তবে আপনি শর্তটির জন্য কোনও ফাংশন লিখতে পারেন।


1

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;
    }
}

ছাঁকনি

জাভা 7

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

জাভা 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"});

বাছাই করা (জাভা 7 এর জন্যও উপলব্ধ)

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

গোষ্ঠীকরণ (জাভা 7 এর জন্যও উপলব্ধ)

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

যোগদান করে (জাভা 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);

1

আমার উত্তরটি কেভিন ওং থেকে তৈরি হয়েছে, এখানে বসন্তCollectionUtils থেকে জাভা 8 লম্বা এক্সপ্রেশন ব্যবহার করে ওয়ান-লাইনার হিসাবে ।

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

এটি আমি যে বিকল্প হিসাবে দেখেছি তার মতোই সংক্ষিপ্ত এবং পঠনযোগ্য (দিক-ভিত্তিক লাইব্রেরি ব্যবহার না করে)

স্প্রিং কালেকশন ইউটিলেটগুলি স্প্রিং সংস্করণ 4.0.০.২ থেকে পাওয়া যায় RE


1

java 8বিশেষত ব্যবহার করে , lambda expressionআপনি নীচের উদাহরণের মতো এটি করতে পারেন:

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

যেখানে প্রতিটি productঅভ্যন্তরের myProductsসংগ্রহের জন্য, যদি prod.price>10তবে এই পণ্যটি নতুন ফিল্টার তালিকায় যুক্ত করুন।


1

তালিকায় ইতিমধ্যে উপস্থিত মানের উপর নির্ভর করে আমার একটি তালিকা ফিল্টার করা দরকার। উদাহরণস্বরূপ, সমস্ত মানগুলি বর্তমান মানের চেয়ে কম অনুসরণ করে সরান। {2 5 3 4 7 5} -> 5 2 5 7}। বা উদাহরণস্বরূপ সমস্ত নকল remove 3 5 4 2 3 5 6 6} -> 5 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;
    }
});

0

পেয়ারা সহ:

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

জাভা 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); 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.