জাভা 8 এ স্ট্রিম কাস্ট করা সম্ভব?


160

জাভা 8 এ স্ট্রিম কাস্ট করা সম্ভব? বলুন যে আমার কাছে অবজেক্টগুলির একটি তালিকা রয়েছে, আমি অতিরিক্ত সমস্ত অবজেক্ট ফিল্টার করার জন্য এই জাতীয় কিছু করতে পারি:

Stream.of(objects).filter(c -> c instanceof Client)

এটির পরে, আমি যদি ক্লায়েন্টদের সাথে কিছু করতে চাই তবে তাদের প্রত্যেককেই আমার কাস্ট করা দরকার:

Stream.of(objects).filter(c -> c instanceof Client)
    .map(c -> ((Client) c).getID()).forEach(System.out::println);

এটিকে কিছুটা কুৎসিত দেখাচ্ছে। পুরো স্ট্রিমটি কোনও অন্য ধরণের কাস্ট করা সম্ভব? Stream<Object>একটি কাস্ট পছন্দ Stream<Client>?

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


3
জাভা রানটাইমের দৃষ্টিকোণ থেকে দুটি স্ট্রিম প্রকার ইতিমধ্যে একই, সুতরাং কোনও কাস্টের প্রয়োজন নেই। কৌশলটি হ'ল এটি সংকলকটির আগে ছিনিয়ে নেওয়া। (এটি ধরে নিলে এটি করা কোনও
অর্থবোধ করে

উত্তর:


283

আমি মনে করি না যে বাক্সটির বাইরে থাকার উপায় আছে। সম্ভবত একটি ক্লিনার সমাধানটি হ'ল:

Stream.of(objects)
    .filter(c -> c instanceof Client)
    .map(c -> (Client) c)
    .map(Client::getID)
    .forEach(System.out::println);

অথবা, মন্তব্যে যেমন পরামর্শ দেওয়া হয়েছে, আপনি সেই castপদ্ধতিটি ব্যবহার করতে পারেন - প্রাক্তনটি পড়তে আরও সহজ হতে পারে:

Stream.of(objects)
    .filter(Client.class::isInstance)
    .map(Client.class::cast)
    .map(Client::getID)
    .forEach(System.out::println);

এটি আমি যা খুঁজছিলাম তা অনেকটাই। আমি অনুমান করি যে আমি এটি উপেক্ষা করেছি যে এটি ক্লায়েন্টের কাছে কাস্ট করা mapএকটি পুনরায় ফিরে আসবে Stream<Client>। ধন্যবাদ!
গল্প

+1 আকর্ষণীয় নতুন উপায়, যদিও তারা নতুন প্রজন্মের ধরণের স্প্যাগেটি-কোডে ঝুঁকি নিয়েছে (অনুভূমিক নয়, উল্লম্ব নয়)
রবারম্যান

@ লর্ডঅফ দ্য পিগস হ্যাঁ এটি কাজ করে যদিও কোডটি পরিষ্কার হয়ে যায় কিনা তা সম্পর্কে আমি নিশ্চিত নই। আমি আমার উত্তরে ধারণা যুক্ত করেছি।
Assylias

38
আপনি ফিল্টারটির সাথে উদাহরণটি " Stream.of(objects).filter(Client.class::isInstance).[...]
সরলকরণ

তীর ছাড়া অংশটি সত্যিই সুন্দর <3
ফ্যাবিচ

14

গোগোভানের উত্তরের পংক্তির পাশাপাশি , আমি এটি নিম্নলিখিতভাবে করছি:

/**
 * Provides various high-order functions.
 */
public final class F {
    /**
     * When the returned {@code Function} is passed as an argument to
     * {@link Stream#flatMap}, the result is a stream of instances of
     * {@code cls}.
     */
    public static <E> Function<Object, Stream<E>> instancesOf(Class<E> cls) {
        return o -> cls.isInstance(o)
                ? Stream.of(cls.cast(o))
                : Stream.empty();
    }
}

এই সহায়ক ফাংশনটি ব্যবহার করে:

Stream.of(objects).flatMap(F.instancesOf(Client.class))
        .map(Client::getId)
        .forEach(System.out::println);

10

পার্টিতে দেরীতে, তবে আমি মনে করি এটি একটি দরকারী উত্তর।

flatMap এটি করার সবচেয়ে সংক্ষিপ্ততম উপায় হবে।

Stream.of(objects).flatMap(o->(o instanceof Client)?Stream.of((Client)o):Stream.empty())

যদি oহয় Clientতবে একক উপাদান দিয়ে একটি স্ট্রিম তৈরি করুন, অন্যথায় খালি স্ট্রিমটি ব্যবহার করুন। এই স্ট্রিমগুলি তখন একটিতে সমতল করা হবে Stream<Client>


আমি এটি বাস্তবায়নের চেষ্টা করেছি, তবে একটি সতর্কতা পেয়েছিলাম যে আমার ক্লাস "চেক করা বা অনিরাপদ অপারেশনগুলি ব্যবহার করে" - এটি কি প্রত্যাশিত?
বিস্মিত

দুর্ভাগ্যবশত হ্যাঁ. আপনি যদি অপারেটরের if/elseপরিবর্তে কোনও ব্যবহার করেন ?:তবে কোনও সতর্কতা থাকবে না। নিশ্চিত আশ্বাস আপনি নিরাপদে সতর্কতা দমন করতে পারেন।
ggovan

3
আসলে এটি দীর্ঘ Stream.of(objects).filter(o->o instanceof Client).map(o -> (Client)o)বা এমনকি দীর্ঘ Stream.of(objects).filter(Client.class::isInstance).map(Client.class::cast)
দিদিয়ের এল

4

এটিকে কিছুটা কুৎসিত দেখাচ্ছে। পুরো স্ট্রিমটি কোনও অন্য ধরণের কাস্ট করা সম্ভব? Stream<Object>একটি কাস্ট পছন্দ Stream<Client>?

না যে সম্ভব হবে না। এটি জাভা ৮-তে নতুন নয় This এটি জেনারিকের ক্ষেত্রে নির্দিষ্ট। একটি List<Object>একটি সুপার প্রকার নয় List<String>, তাই আপনি শুধু একটি নিক্ষেপ করতে পারবে না List<Object>একটি থেকে List<String>

অনুরূপ এখানে সমস্যা। আপনি কাস্ট Stream<Object>করতে পারবেন না Stream<Client>। অবশ্যই আপনি এটিকে অপ্রত্যক্ষভাবে কাস্ট করতে পারেন:

Stream<Client> intStream = (Stream<Client>) (Stream<?>)stream;

তবে এটি নিরাপদ নয় এবং রানটাইম এ ব্যর্থ হতে পারে। এর অন্তর্নিহিত কারণটি হ'ল, জাভাতে জেনেরিকগুলি ক্ষয় ব্যবহার করে প্রয়োগ করা হয়। সুতরাং, Streamরানটাইমে এটি কোন ধরণের তা সম্পর্কে কোনও ধরণের তথ্য পাওয়া যায়নি । সবকিছু ঠিক আছে Stream

বিটিডাব্লু, আপনার পদ্ধতির সাথে কী দোষ? আমার কাছে ভাল লাগছে।


2
@ ডিআর জেনারিকস ইন রিফায়েন্স C#ব্যবহার করে প্রয়োগ করা হয়, যখন জাভাতে এটি ক্ষয় ব্যবহার করে প্রয়োগ করা হয়। উভয়ই বিভিন্ন ফ্যাশন অন্তর্নিহিত প্রয়োগ করা হয়। সুতরাং আপনি এটি উভয় ভাষায় একইভাবে কাজ করার আশা করতে পারবেন না।
রোহিত জৈন

1
@ ডিআর আমি বুঝতে পারি যে মুছে ফেলা জাভাতে জেনারিকের ধারণাটি শুরু করার জন্য প্রাথমিকভাবে অনেকগুলি বিষয়কে তুলে ধরেছে। এবং যেহেতু আমি সি # ব্যবহার করি না, তাই তুলনা সম্পর্কে আমি খুব বেশি বিশদে যেতে পারি না। তবে এইভাবে আইএমও প্রয়োগের পেছনে পুরো অনুপ্রেরণা ছিল জেভিএম বাস্তবায়নে বড় পরিবর্তন এড়ানো।
রোহিত জৈন

1
কেন এটি "অবশ্যই রানটাইমে ব্যর্থ হবে"? আপনি যেহেতু বলেন (জেনেরিক) ধরণের তথ্য নেই, তাই রানটাইম যাচাই করার জন্য কিছুই নেই। এটি সম্ভবত রানটাইমের সময় ব্যর্থ হতে পারে , যদি ভুল ধরণের মাধ্যমে খাওয়ানো হয় তবে সে সম্পর্কে কোনও "নিশ্চিততা" নেই।
হট লিক্স

1
@ রোহিতজাইন: আমি জাভার জেনেরিক ধারণার সমালোচনা করছি না, তবে এই একক পরিণতি এখনও কুৎসিত কোড তৈরি করে ;-)
ডিআর

1
@ ডিআর - জাভা জেনেরিকগুলি গিটগো থেকে কুৎসিত। বেশিরভাগ ক্ষেত্রে কেবল সি ++ বৈশিষ্ট্য অভিলাষ।
হট লিক্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.