ভবিষ্যদ্বাণী দ্বারা প্রথম উপাদান সন্ধান করুন


504

আমি সবেমাত্র জাভা 8 ল্যাম্বডাসের সাথে খেলতে শুরু করেছি এবং আমি কার্যকরী ভাষায় কিছু ব্যবহার করার চেষ্টা করছি implement

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

lst.stream()
    .filter(x -> x > 5)
    .findFirst()

তবে এটি আমার পক্ষে অকার্যকর বলে মনে হচ্ছে, কারণ ফিল্টার পুরো তালিকাটি স্ক্যান করবে, অন্তত আমার বোঝার জন্য (যা ভুল হতে পারে)। একটি ভাল উপায় আছে কি?


53
এটি অদক্ষ নয়, জাভা 8 স্ট্রিম প্রয়োগটি অলসভাবে মূল্যায়ন করা হয়েছে, সুতরাং ফিল্টারটি কেবলমাত্র টার্মিনাল অপারেশনে প্রয়োগ করা হয়। এখানে একই প্রশ্ন: স্ট্যাকওভারফ্লো
মেরেক গ্রেগর

1
কুল। আমি আশা করি এটি করত। এটি অন্যথায় একটি বড় ডিজাইন ফ্লপ হত।
siki

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

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

উত্তর:


720

না, ফিল্টার পুরো স্ট্রিমটি স্ক্যান করে না। এটি একটি মধ্যবর্তী অপারেশন, যা একটি অলস প্রবাহ ফিরিয়ে দেয় (আসলে সমস্ত মধ্যবর্তী ক্রিয়াকলাপ একটি অলস প্রবাহ ফিরিয়ে দেয়)। আপনাকে বোঝাতে, আপনি কেবল নিম্নলিখিত পরীক্ষাটি করতে পারেন:

List<Integer> list = Arrays.asList(1, 10, 3, 7, 5);
int a = list.stream()
            .peek(num -> System.out.println("will filter " + num))
            .filter(x -> x > 5)
            .findFirst()
            .get();
System.out.println(a);

কোন ফলাফল:

will filter 1
will filter 10
10

আপনি দেখতে পেয়েছেন যে কেবলমাত্র স্ট্রিমের দুটি প্রথম উপাদানই বাস্তবে প্রক্রিয়াভুক্ত।

সুতরাং আপনি আপনার পদ্ধতির সাথে যেতে পারেন যা পুরোপুরি ঠিক আছে।


37
একটি নোট হিসাবে, আমি get();এখানে ব্যবহার করেছি কারণ আমি জানি যে আমি স্ট্রিম পাইপলাইনে কোন মানগুলি খাওয়াচ্ছি এবং ফলস্বরূপ ফলাফল হবে। অনুশীলনে, আপনার ব্যবহার করা উচিত নয় get();, তবে orElse()/ orElseGet()/ orElseThrow()(এনএসইইয়ের পরিবর্তে আরও অর্থবহ ত্রুটির জন্য) আপনি জানেন না যে স্ট্রিম পাইপলাইনে প্রয়োগ করা ক্রিয়াকলাপগুলির কোনও উপাদানটির ফলাফল হবে কিনা will
অ্যালেক্সিস সি

31
.findFirst().orElse(null);উদাহরণস্বরূপ
গন্ডি

20
OrElse নাল ব্যবহার করবেন না। এটি একটি অ্যান্টি-প্যাটার্ন হওয়া উচিত। এগুলি সমস্ত inচ্ছিকতে অন্তর্ভুক্ত রয়েছে সুতরাং আপনি কেন এনপিইর ঝুঁকি নেবেন? আমি মনে করি ptionচ্ছিকের সাথে ডিল করা ভাল উপায়। আপনি এটি ব্যবহার করার আগে কেবল Pচ্ছিককে isPLive () দিয়ে পরীক্ষা করুন।
বেজে

@ বেজে আমি বুঝতে পারছি না এর পরিবর্তে আমার কী ব্যবহার করা উচিত orElse?
জন হেন্কেল

3
@ জোহেন হ্যাঙ্কেল আমি মনে করি বেজে এর অর্থ হ'ল আপনার এটিকে একটি Optionalধরণ হিসাবে ছেড়ে দেওয়া উচিত , যা .findFirstপ্রত্যাবর্তন করে। nullPtionচ্ছিকর ব্যবহারগুলির মধ্যে একটি হ'ল বিকাশকারীদের চেকিংয়ের পরিবর্তে সেগের সাথে ডিল myObject != nullকরতে না দেওয়া, আপনি চেক করতে myOptional.isPresent()বা ptionচ্ছিক ইন্টারফেসের অন্যান্য অংশগুলি ব্যবহার করতে পারেন । এটি কি আরও পরিষ্কার করে দিয়েছে?
এএমটার্প

102

তবে এটি আমার পক্ষে অকার্যকর বলে মনে হচ্ছে, কারণ ফিল্টারটি পুরো তালিকাটি স্ক্যান করবে

না এটি হবে না - শিকারীর তুষ্টকারী প্রথম উপাদানটি পাওয়া মাত্র এটি "ব্রেক" হয়ে যাবে। আপনি স্ট্রিম প্যাকেজ জাভাদোকে অলসতা সম্পর্কে আরও পড়তে পারেন , বিশেষত (জোর দেওয়া খনি):

ফিল্টারিং, ম্যাপিং বা সদৃশ অপসারণের মতো অনেক স্ট্রিম ক্রিয়াকলাপটি অলসভাবে প্রয়োগ করা যেতে পারে, অপ্টিমাইজেশনের সুযোগগুলি প্রকাশ করে। উদাহরণস্বরূপ, "টানা তিনটি স্বরযুক্ত প্রথম স্ট্রিংটি সন্ধান করুন" সমস্ত ইনপুট স্ট্রিং পরীক্ষা করার দরকার নেই। স্ট্রিম অপারেশনগুলি মধ্যবর্তী (স্ট্রিম উত্পাদনকারী) অপারেশন এবং টার্মিনাল (মান- বা পার্শ্ব-প্রতিক্রিয়া-উত্পাদনকারী) ক্রিয়ায় বিভক্ত। মধ্যবর্তী অপারেশন সবসময় অলস হয়।


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

30
return dataSource.getParkingLots()
                 .stream()
                 .filter(parkingLot -> Objects.equals(parkingLot.getId(), id))
                 .findFirst()
                 .orElse(null);

আমাকে অবজেক্টের তালিকা থেকে কেবল একটি অবজেক্ট ফিল্টার করতে হয়েছিল। সুতরাং আমি এটি ব্যবহার করেছি, আশা করি এটি সাহায্য করবে।


আরও ভাল: যেহেতু আমরা একটি বুলিয়ান রিটার্ন মান খুঁজছি, আমরা নাল চেক যোগ করে এটি আরও ভাল করতে পারি: ডেটাসোর্স.টেটপার্টিংলটস () স্ট্রিম () ফিল্টার (পার্কিংলট -> অবজেক্টস.কিয়ালস (পার্কিংলট.জেটআইডি (), আইডি)) .findFrst ()। orElse (নাল)! = নাল;
শ্রীধর ভাট

1
@ Shreedharbhat- কে আপনার করা উচিত নয় .orElse(null) != null। পরিবর্তে theচ্ছিক এপিআই এর .isPresentঅর্থ ব্যবহার করুন .findFirst().isPresent()
এএমটার্প

@ শ্রীধরভাট সবার আগে ওপি কোনও বুলিয়ান রিটার্ন মান খুঁজছিলেন না। সব যদি তারা ছিল দ্বিতীয়ত, এটা লিখতে ক্লিনার হয়েছে হবে.stream().map(ParkingLot::getId).anyMatch(Predicate.isEqual(id))
AjaxLeung

13

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

Integer a = list.stream()
                .peek(num -> System.out.println("will filter " + num))
                .filter(x -> x > 5)
                .findFirst()
                .orElse(null);

তারপর আপনি কেবল পরীক্ষা পারে কিনা একটি হল null


1
আপনার উদাহরণ ঠিক করা উচিত। আপনি একটি প্লে ইন্টে নাল বরাদ্দ করতে পারবেন না। stackoverflow.com/questions/2254435/can-an-int-be-null-in-java
RubioRic

আমি আপনার পোস্ট সম্পাদনা করেছি। 0 (শূন্য) একটি সংখ্যার কার্যকর ফলাফল হতে পারে যখন আপনি পূর্ণসংখ্যার তালিকায় অনুসন্ধান করছেন। পূর্ণসংখ্যার দ্বারা পরিবর্তনশীল প্রকার এবং নাল দ্বারা ডিফল্ট মান প্রতিস্থাপন।
রুবিওরিক

0

import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

// Stream is ~30 times slower for same operation...
public class StreamPerfTest {

    int iterations = 100;
    List<Integer> list = Arrays.asList(1, 10, 3, 7, 5);


    // 55 ms
    @Test
    public void stream() {

        for (int i = 0; i < iterations; i++) {
            Optional<Integer> result = list.stream()
                    .filter(x -> x > 5)
                    .findFirst();

            System.out.println(result.orElse(null));
        }
    }

    // 2 ms
    @Test
    public void loop() {

        for (int i = 0; i < iterations; i++) {
            Integer result = null;
            for (Integer walk : list) {
                if (walk > 5) {
                    result = walk;
                    break;
                }
            }
            System.out.println(result);
        }
    }
}

0

উন্নত ওয়ান-লাইনারের উত্তর: আপনি যদি বুলিয়ান রিটার্ন মান খুঁজছেন, তবে আমরা এটিপসেস যোগ করে আরও ভাল করতে পারি:

return dataSource.getParkingLots().stream().filter(parkingLot -> Objects.equals(parkingLot.getId(), id)).findFirst().isPresent();

আপনি যদি বুলিয়ান রিটার্ন মান চান তবে আপনার যে কোনও ম্যাচ ব্যবহার করা উচিত
আজাক্সলুং
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.