একটি জাভা পদ্ধতি থেকে একাধিক অবজেক্ট কীভাবে ফিরে আসবেন?


172

আমি একটি জাভা পদ্ধতি থেকে দুটি অবজেক্ট ফিরিয়ে দিতে চাই এবং ভাবছিলাম যে এটি করার ভাল উপায় কী হতে পারে?

সম্ভাব্য উপায় আমি মনে করতে পারেন আছেন: রিটার্ন একটি HashMap(যেহেতু দুটি বস্তুর সম্পর্কিত হয়) অথবা একটি ফিরে আসতে ArrayListএরObject অবজেক্ট।

আরও সুনির্দিষ্টভাবে বলতে গেলে যে দুটি বস্তু আমি ফিরে আসতে চাই তা হ'ল (ক) List হ'ল (ক) অবজেক্ট এবং (খ) কমা পৃথক পৃথক নামের।

আমি এই দুটি অবজেক্টকে একটি পদ্ধতি থেকে ফিরে আসতে চাই কারণ কমা দ্বারা পৃথক করা নামগুলি পেতে (যা আমি এই পদ্ধতিতে একই লুপে করতে পারি) পেতে বস্তুর তালিকার মাধ্যমে পুনরাবৃত্তি করতে চাই না।

একরকম, HashMapকোনও ফেরত দেওয়া এটির জন্য খুব মার্জিত উপায় মনে হয় না।


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

উত্তর:


128

আপনি যদি দুটি বস্তু ফিরিয়ে দিতে চান তবে আপনি সাধারণত কোনও একক বস্তুটি ফিরিয়ে দিতে চান যা পরিবর্তে দুটি বস্তুকে সজ্জিত করে।

আপনি NamedObjectএই জাতীয় বস্তুর একটি তালিকা ফিরে আসতে পারেন :

public class NamedObject<T> {
  public final String name;
  public final T object;

  public NamedObject(String name, T object) {
    this.name = name;
    this.object = object;
  }
}

তারপর আপনি সহজেই একটি আসতে পারেন List<NamedObject<WhateverTypeYouWant>>

এছাড়াও: আপনি কেন একটি পরিবর্তে কমা দ্বারা বিচ্ছিন্ন নামের তালিকা ফিরিয়ে দিতে চান List<String>? বা আরও ভাল, Map<String,TheObjectType>কীগুলির সাথে নাম এবং মানগুলির মানগুলি দিয়ে ফিরে আসুন (যদি না আপনার বস্তুগুলি ক্রম নির্দিষ্ট করে দেয়, তবে এক্ষেত্রে কোনওটি NavigableMapআপনি চান তা হতে পারে।


কমা দ্বারা বিচ্ছিন্ন তালিকায় ফিরে আসার কারণ হ'ল: আমি যদি এখানে তালিকা তৈরি না করি তবে অবজেক্টগুলির মধ্য দিয়ে লুপিং করে আমাকে কলারে এটি করতে হবে (সিএস মান প্রয়োজন)। সম্ভবত, আমি অকারণে প্রাক-অনুকূলকরণ করছি।
জগমল

2
আমি সবসময় ভাবছিলাম যে এই কারণে জাভাটির একটি জোড় <টি, ইউ> শ্রেণি নেই কেন।
ডেভিড কোয়েল

জগমল: হ্যাঁ, যদি কমা-বিচ্ছিন্ন তালিকায় ফিরে আসার একমাত্র রাসন এই অপটিমাইজেশন হয়, তবে এটি ভুলে যান।
জোছিম সউর 14

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

@ ডেভিড: আমি সম্মত হই যে এখানে অবজেক্ট ব্যবহার করা খুব ঝরঝরে নয় তবে আবার কোনও সাধারণ পূর্বপুরুষ ছাড়া বস্তুগুলি ফেরত পাঠানো (অবশ্যই অবজেক্ট ছাড়া) খুব পরিষ্কার নয় isn't এমনকি আমি এটি বলতে চাই এটি একটি কোড গন্ধ, যদি আপনার এটির প্রয়োজন হয়।
জোছিম সউর

69

আপনি যদি জানেন যে আপনি দুটি বস্তু ফিরিয়ে দিতে চলেছেন তবে আপনি জেনেরিক জোড়ও ব্যবহার করতে পারেন:

public class Pair<A,B> {
    public final A a;
    public final B b;

    public Pair(A a, B b) {
        this.a = a;
        this.b = b;
    }
};

সম্পাদনা করুন আরো একটি সম্পূর্ণরূপে গঠিত উপরে বাস্তবায়ন:

package util;

public class Pair<A,B> {

    public static <P, Q> Pair<P, Q> makePair(P p, Q q) {
        return new Pair<P, Q>(p, q);
    }

    public final A a;
    public final B b;

    public Pair(A a, B b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((a == null) ? 0 : a.hashCode());
        result = prime * result + ((b == null) ? 0 : b.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        @SuppressWarnings("rawtypes")
        Pair other = (Pair) obj;
        if (a == null) {
            if (other.a != null) {
                return false;
            }
        } else if (!a.equals(other.a)) {
            return false;
        }
        if (b == null) {
            if (other.b != null) {
                return false;
            }
        } else if (!b.equals(other.b)) {
            return false;
        }
        return true;
    }

    public boolean isInstance(Class<?> classA, Class<?> classB) {
        return classA.isInstance(a) && classB.isInstance(b);
    }

    @SuppressWarnings("unchecked")
    public static <P, Q> Pair<P, Q> cast(Pair<?, ?> pair, Class<P> pClass, Class<Q> qClass) {

        if (pair.isInstance(pClass, qClass)) {
            return (Pair<P, Q>) pair;
        }

        throw new ClassCastException();

    }

}

নোটগুলি, প্রধানত জাভা এবং জেনেরিকের সাথে মরিচা ঘিরে:

  • উভয় aএবং bঅপরিবর্তনীয়।
  • makePairস্থির পদ্ধতি আপনাকে বয়লার প্লেট টাইপিংয়ে সহায়তা করে যা জাভা 7-এ হীরা অপারেটরটি কম বিরক্তিকর করবে। এটি সত্যিই সুন্দর পুনরায় তৈরি করার জন্য কিছু কাজ রয়েছে: জেনেরিকস, তবে এটি এখন ঠিক আছে। (সিএফ পিইসিএস)
  • hashcodeএবং equalsগ্রহন দ্বারা উত্পন্ন হয়।
  • castপদ্ধতিতে ileালাই সংকলনের সময় ঠিক আছে, তবে একেবারেই সঠিক বলে মনে হচ্ছে না।
  • ওয়াইল্ডকার্ডগুলি isInstanceপ্রয়োজনীয় কিনা তা আমি নিশ্চিত নই ।
  • আমি কেবল মন্তব্যের জবাবে এটি লিখেছি, কেবল উদাহরণের উদ্দেশ্যে।

আমি সাধারণত প্রতিটি ক্লাসে কাজ করি এমন ক্লাসটি আমার কাছে থাকে। আমি আরও যুক্ত করব: একটি হ্যাশকোড / সমান বাস্তবায়ন এবং সম্ভবত একটি স্ট্যাটিক আইসনস্ট্যান্স () এবং castালাই () পদ্ধতি।
জামেশ

অবশ্যই, এই শ্রেণিটি আরও চৌকস এবং আরও বেশি সুবিধাজনক হিসাবে ব্যবহার করার উপায় রয়েছে। উপরের সংস্করণে একটি শট ঘোষণার মধ্যে যা যথেষ্ট তা অন্তর্ভুক্ত রয়েছে।
ডেভিড হানাক

@ জামেশ: আপনার বিবরণটি এখানে পুরো বিশদে লিখতে আপত্তি আছে? আমি "হ্যাশকোড / সমান বাস্তবায়ন এবং সম্ভবত একটি স্ট্যাটিক আইসনস্ট্যান্স () এবং castালাই () পদ্ধতি সরবরাহ করার পরে এটি দেখতে কেমন তা জানতে চাই।" ধন্যবাদ.
কিয়াং লি

@ কিয়াংলি - আমি সাধারণত হ্যাশকোড উত্পন্ন করি এবং পদ্ধতিগুলির সমান। তাত্ক্ষণিক পদ্ধতিটি হল ইনস্ট্যান্স দুটি ক্লাস নেয় এবং তা নিশ্চিত করে যে দৃষ্টান্তের একটি & বি সেই শ্রেণীর উদাহরণ। কাস্ট একটি জুড়ি <?,?> নেয় এবং সাবধানে এটিকে একটি জোড় <<, বি> এ জুড়ে দেয়। বাস্তবায়নগুলি মোটামুটি সহজ হওয়া উচিত (ইঙ্গিত: Class.cast (), Class.isInstance ())
জমেশ

2
এটি খুব সুন্দর Pairবাস্তবায়ন একটি ছোটখাটো পরিবর্তন আমি করব: দস্তাবেজটিতে একটি বার্তা যুক্ত করুন ClassCastException। অন্যথায় যদি কোনও কারণে এটি ব্যর্থ হয় তবে ডিবাগিং একটি দুঃস্বপ্ন হয়ে যায়। (এবং কাঁচা টাইপস-দমন-সতর্কতাগুলি অপ্রয়োজনীয় হবে যদি আপনি কাস্ট করেন তবে Pair<?,?>(যা কাজ করে, কারণ আপনার কেবলমাত্র এর Objectথেকে পদ্ধতি প্রয়োজন aএবং b)) আমি কোডটি টুইট করে দিলে কি আপত্তি আছে?
জোছিম সউর

25

ইভেন্টে আপনি যে পদ্ধতিতে কল করছেন সেটি ব্যক্তিগত, বা একটি অবস্থান থেকে কল করা আছে, চেষ্টা করুন

return new Object[]{value1, value2};

কলারের মতো দেখতে:

Object[] temp=myMethod(parameters);
Type1 value1=(Type1)temp[0];  //For code clarity: temp[0] is not descriptive
Type2 value2=(Type2)temp[1];

ডেভিড হানকের জোড়ের উদাহরণটির কোনও সিন্ট্যাক্টিক সুবিধা নেই এবং এটি দুটি মানেই সীমাবদ্ধ।

return new Pair<Type1,Type2>(value1, value2);

এবং কলকারী দেখতে দেখতে:

Pair<Type1, Type2> temp=myMethod(parameters);
Type1 value1=temp.a;  //For code clarity: temp.a is not descriptive
Type2 value2=temp.b;


5
আইএমএইচও, এই পথে যাবেন না - ঘোষণাপত্রে প্রত্যাশিত প্রত্যাবর্তনের মানগুলি সম্পর্কে খুব সামান্যই বলা হয়েছে। আফাইক, জেনেরিক ক্লাস তৈরি করা আরও বেশি পছন্দ করা হয় যা নির্দিষ্ট করে দেয় যে কতগুলি পরামিতি প্রত্যাবর্তন হচ্ছে এবং সেই পরামিতিগুলির ধরণ। Pair<T1, T2>, Tuple<T1, T2, T3>, Tuple<T1, T2, T3, T4>, ইত্যাদি তারপর একটি নির্দিষ্ট ব্যবহারের শো সংখ্যা এবং পরামিতি ধরনের Pair<int, String> temp = ...বা যাই হোক না কেন।
টুলমেকারস্টেভ

22

আপনি নিম্নলিখিত কোনও উপায় ব্যবহার করতে পারেন:

private static final int RETURN_COUNT = 2;
private static final int VALUE_A = 0;
private static final int VALUE_B = 1;
private static final String A = "a";
private static final String B = "b";

1) অ্যারে ব্যবহার

private static String[] methodWithArrayResult() {
    //...
    return new String[]{"valueA", "valueB"};
}

private static void usingArrayResultTest() {
    String[] result = methodWithArrayResult();
    System.out.println();
    System.out.println("A = " + result[VALUE_A]);
    System.out.println("B = " + result[VALUE_B]);
}

2) অ্যারেলিস্ট ব্যবহার করে

private static List<String> methodWithListResult() {
    //...
    return Arrays.asList("valueA", "valueB");
}

private static void usingListResultTest() {
    List<String> result = methodWithListResult();
    System.out.println();
    System.out.println("A = " + result.get(VALUE_A));
    System.out.println("B = " + result.get(VALUE_B));
}

3) হ্যাশম্যাপ ব্যবহার করা

private static Map<String, String> methodWithMapResult() {
    Map<String, String> result = new HashMap<>(RETURN_COUNT);
    result.put(A, "valueA");
    result.put(B, "valueB");
    //...
    return result;
}

private static void usingMapResultTest() {
    Map<String, String> result = methodWithMapResult();
    System.out.println();
    System.out.println("A = " + result.get(A));
    System.out.println("B = " + result.get(B));
}

4) আপনার কাস্টম ধারক ক্লাস ব্যবহার

private static class MyContainer<M,N> {
    private final M first;
    private final N second;

    public MyContainer(M first, N second) {
        this.first = first;
        this.second = second;
    }

    public M getFirst() {
        return first;
    }

    public N getSecond() {
        return second;
    }

    // + hashcode, equals, toString if need
}

private static MyContainer<String, String> methodWithContainerResult() {
    //...
    return new MyContainer("valueA", "valueB");
}

private static void usingContainerResultTest() {
    MyContainer<String, String> result = methodWithContainerResult();
    System.out.println();
    System.out.println("A = " + result.getFirst());
    System.out.println("B = " + result.getSecond());
}

5) অ্যাবস্ট্র্যাক্টম্যাপ.সিম্পেলএন্ট্রি ব্যবহার করে

private static AbstractMap.SimpleEntry<String, String> methodWithAbstractMapSimpleEntryResult() {
    //...
    return new AbstractMap.SimpleEntry<>("valueA", "valueB");
}

private static void usingAbstractMapSimpleResultTest() {
    AbstractMap.SimpleEntry<String, String> result = methodWithAbstractMapSimpleEntryResult();
    System.out.println();
    System.out.println("A = " + result.getKey());
    System.out.println("B = " + result.getValue());
}

6) ব্যবহার জুড়ি এর এ্যাপাচি কমন্স

private static Pair<String, String> methodWithPairResult() {
    //...
    return new ImmutablePair<>("valueA", "valueB");
}

private static void usingPairResultTest() {
    Pair<String, String> result = methodWithPairResult();
    System.out.println();
    System.out.println("A = " + result.getKey());
    System.out.println("B = " + result.getValue());
}

16

আমি জাভাতে কোড দিই আমি প্রায় সবসময় এন-টুপল ক্লাস সংজ্ঞায়িত করি। এই ক্ষেত্রে:

public class Tuple2<T1,T2> {
  private T1 f1;
  private T2 f2;
  public Tuple2(T1 f1, T2 f2) {
    this.f1 = f1; this.f2 = f2;
  }
  public T1 getF1() {return f1;}
  public T2 getF2() {return f2;}
}

আমি জানি এটি কিছুটা কুৎসিত, তবে এটি কাজ করে এবং আপনাকে কেবল একবার আপনার টিউপলের ধরণের সংজ্ঞা দিতে হবে। টিপলস জাভা সত্যিই অভাব এমন কিছু।

সম্পাদনা: ডেভিড হানাকের উদাহরণটি আরও মার্জিত, কারণ এটি গেটারদের সংজ্ঞা দেওয়া থেকে বিরত থাকে এবং এখনও অবজেক্টটিকে স্থির রাখে।


9

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

সুতরাং আপনার পদ্ধতিটি এর মতো দেখতে পারে:

public Map<String, MyType> doStuff();

আপনি যে ধরনের অবজেক্টে ফিরে আসছেন সে ধরণের মাইটাইপ অবশ্যই।

মূলত আমি মনে করি যে মানচিত্র ফিরিয়ে দেওয়া এই ক্ষেত্রে সঠিক সমাধান কারণ আপনি ঠিক এটিই ফিরিয়ে দিতে চান - কোনও বস্তুর সাথে স্ট্রিংয়ের ম্যাপিং।


নামের কোনওটি সংঘর্ষিত হলে এটি কাজ করবে না। একটি তালিকায় সদৃশগুলি থাকতে পারে তবে মানচিত্রে (সদৃশ কীগুলি থাকতে পারে না)।
tvanfosson

অবশ্যই. আমি প্রশ্নের ভিত্তিতে অনুমানগুলি তৈরি করছিলাম - সম্ভবত অযৌক্তিকভাবে :)
কিপজ

যদিও আপনার অনুমানটি এই ক্ষেত্রে সত্য ধারন করে, আমি অকাল অপটিমাইজেশনের ডোমেনে চলে যাচ্ছি (যা আমার করা উচিত নয়)।
জগমল

6

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

আপনার বিশেষ সমস্যাটির সাথে এটি দেখতে এমন কিছু দেখাচ্ছে:

public class ResultsConsumer implements ResultsGenerator.ResultsCallback
{
    public void handleResult( String name, Object value )
    {
        ... 
    }
}

public class ResultsGenerator
{
    public interface ResultsCallback
    {
        void handleResult( String aName, Object aValue );
    }

    public void generateResults( ResultsGenerator.ResultsCallback aCallback )
    {
        Object value = null;
        String name = null;

        ...

        aCallback.handleResult( name, value );
    }
}

আপনার খুব পুরানো উত্তর সম্পর্কে মন্তব্য করার জন্য দুঃখিত, কিন্তু কলব্যাকগুলি কীভাবে আবর্জনা সংগ্রহের ক্ষেত্রে যায়? মেমোরি ম্যানেজমেন্ট সম্পর্কে আমার অবশ্যই খুব ভাল ধারণা নেই java, যদি আপনার কাছে অবজেক্ট Aকল অবজেক্ট B.getResult()এবং একটি হিসাবে B.getResult()কল A.finishResult()করা callbackথাকে তবে কী জিনিসটি Bআবর্জনা সংগ্রহ করে বা এটি শেষ না হওয়া অবধি থাকে না ?? সম্ভবত একটি বোকা প্রশ্ন কিন্তু এটি আমার একটি মৌলিক বিভ্রান্তি!
তারে00

6

অ্যাপাচি কমন্স এর জন্য টিপল এবং ট্রিপল রয়েছে:

  • ImmutablePair<L,R> দুটি অবজেক্ট উপাদান সমন্বিত একটি অপরিবর্তনীয় জুটি।
  • ImmutableTriple<L,M,R> তিনটি অবজেক্ট উপাদান সমন্বিত একটি অপরিবর্তনীয় ট্রিপল।
  • MutablePair<L,R> দুটি অবজেক্ট উপাদান সমন্বিত একটি পরিবর্তনীয় জুটি।
  • MutableTriple<L,M,R> তিনটি অবজেক্ট উপাদান সমন্বিত একটি পরিবর্তনীয় ট্রিপল।
  • Pair<L,R> দুটি উপাদান নিয়ে গঠিত একটি জুড়ি।
  • Triple<L,M,R> তিনটি উপাদান সমন্বিত একটি ট্রিপল।

সূত্র: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html


6

আপনার ক্ষেত্রে থাকাকালীন , অ্যান্ড্রয়েডে, মন্তব্যটি যাওয়ার ভাল উপায় হতে পারে, আপনি ব্যবহার করতে পারেন Pair । কেবল

return new Pair<>(yourList, yourCommaSeparatedValues);

5

নিম্নলিখিত এন্ট্রি অবজেক্টের উদাহরণ উদাহরণ:

public Entry<A,B> methodname(arg)
{
.......

return new AbstractMap.simpleEntry<A,B>(instanceOfA,instanceOfB);
}

5

একাধিক রিটার্ন মান সম্পর্কে ইস্যুটি সম্পর্কে আমি সাধারণত একটি ছোট সহায়ক সহায়ক বর্গ ব্যবহার করি যা একক রিটার্ন মানকে আবৃত করে এবং পদ্ধতিতে প্যারামিটার হিসাবে পাস হয়:

public class ReturnParameter<T> {
    private T value;

    public ReturnParameter() { this.value = null; }
    public ReturnParameter(T initialValue) { this.value = initialValue; }

    public void set(T value) { this.value = value; }
    public T get() { return this.value; }
}

(আদিম ডেটাটাইপগুলির জন্য আমি সরাসরি মান সংরক্ষণ করতে ছোটখাটো প্রকরণ ব্যবহার করি)

এমন একটি পদ্ধতি যা একাধিক মান ফিরিয়ে দিতে চায় তা নীচে ঘোষণা করা হবে:

public void methodThatReturnsTwoValues(ReturnParameter<ClassA> nameForFirstValueToReturn, ReturnParameter<ClassB> nameForSecondValueToReturn) {
    //...
    nameForFirstValueToReturn.set("...");
    nameForSecondValueToReturn.set("...");
    //...
}

সম্ভবত বড় অসুবিধা হ'ল কলারকে রিটার্নের জিনিসগুলি সেগুলি ব্যবহার করতে চাইলে আগেই প্রস্তুত করতে হয় (এবং পদ্ধতিটি নাল পয়েন্টারগুলির জন্য পরীক্ষা করা উচিত)

ReturnParameter<ClassA> nameForFirstValue = new ReturnParameter<ClassA>();
ReturnParameter<ClassB> nameForSecondValue = new ReturnParameter<ClassB>();
methodThatReturnsTwoValues(nameForFirstValue, nameForSecondValue);

সুবিধা (প্রস্তাবিত অন্যান্য সমাধানের তুলনায়):

  • আপনাকে পৃথক পদ্ধতি এবং এর ফেরতের প্রকারের জন্য একটি বিশেষ শ্রেণীর ঘোষণা তৈরি করতে হবে না
  • প্যারামিটারগুলি একটি নাম পায় এবং তাই পদ্ধতি স্বাক্ষরের দিকে তাকানোর সময় পার্থক্য করা সহজ
  • প্রতিটি প্যারামিটারের জন্য সুরক্ষা টাইপ করুন

প্রত্যাবর্তিত মান ধরণের সেট অনুসারে শ্রেণি ঘোষণার প্রয়োজন ছাড়াই, এমন প্রতিটি সমাধানের জন্য নাম এবং প্রকার সুরক্ষা দেয় এমন একটি সমাধানের জন্য ধন্যবাদ।
টুলমেকারস্টেভ

3

সমস্ত সম্ভাব্য সমাধানগুলি ক্লডজ (যেমন ধারক বস্তুগুলির মতো, আপনার হ্যাশম্যাপ ধারণা, অ্যারের মাধ্যমে উপলব্ধ হিসাবে "একাধিক রিটার্ন মান") হবে। আমি প্রত্যাবর্তিত তালিকা থেকে কমা-বিচ্ছিন্ন তালিকাটি পুনঃজেনার করার পরামর্শ দিচ্ছি। কোডটি অনেক ক্লিনার হয়ে শেষ হবে।


আমি এটিতে আপনার সাথে একমত হই তবে আমি যদি এটি করি তবে আমি দুবার লুপিং শেষ করব (বিদ্যমান পদ্ধতিতে আমি আসলে তালিকার একের পর এক উপাদান তৈরি করছি)।
জগমল

1
@ জাগমাল: আপনি হয়ত দু'বার লুপ করবেন তবে বেশিরভাগ সময় এটি গুরুত্ব দেয় না (গিজমোসের উত্তর দেখুন)।
জোছিম সৌর

1
হ্যাঁ, আপনার কোডটি অপছন্দ করার চেষ্টা করবেন না যদি না আপনার সত্যিই দরকার হয়। গিজমো যে সম্পর্কে খুব সঠিক।
বোম্বে

3

এটি সহজ রাখুন এবং একাধিক ফলাফলের পরিস্থিতির জন্য একটি শ্রেণী তৈরি করুন। এই উদাহরণটি একটি অ্যারেলিস্ট এবং একটি ডেটাবেসহেল্পার getInfo থেকে একটি বার্তা পাঠ্য গ্রহণ করে।

যেখানে আপনি রুটিনটিকে কল করেন যা আপনাকে কোড দেয় একাধিক মানকে:

multResult res = mydb.getInfo(); 

রুটিনে আপনার কোড কোডটি পান:

ArrayList<String> list= new ArrayList<String>();
add values to the list...
return new multResult("the message", list);

এবং এর সাথে ক্লাসের বহু ফলাফলের সংজ্ঞা দিন:

public class multResult {
    public String message; // or create a getter if you don't like public
    public ArrayList<String> list;
    multResult(String m, ArrayList<String> l){
        message = m;
        list= l;
}

}


2

আমি দেখতে পাচ্ছি এখানে সত্যিই তিনটি পছন্দ আছে এবং সমাধানটি প্রসঙ্গে নির্ভর করে context আপনি তালিকা তৈরির পদ্ধতিতে নামটির নির্মাণ বাস্তবায়ন করতে বেছে নিতে পারেন। এটি আপনার পছন্দ হিসাবে বেছে নেওয়া হয়েছে, তবে আমি মনে করি এটি সেরা নয়। আপনি উত্পাদক পদ্ধতিতে গ্রাসকারী পদ্ধতিতে একটি সংযোগ তৈরি করছেন যাটির অস্তিত্বের প্রয়োজন নেই। অন্যান্য কলকারীদের অতিরিক্ত তথ্যের প্রয়োজন নাও হতে পারে এবং আপনি এই কলকারীদের অতিরিক্ত তথ্য গণনা করবেন be

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

শেষ অবধি, নামটি তৈরি করার জন্য আপনি নিজেই তালিকাটি দায়বদ্ধ হতে পারেন। যদি একাধিক কলার দ্বারা গণনা করা দরকার হয় তবে আমি এই পথে যাব। আমি মনে করি এটি ক্লাসের সাথে নাম তৈরির জন্য দায়বদ্ধ করে তোলে যা বস্তুগুলির সাথে তাদের সবচেয়ে ঘনিষ্ঠভাবে জড়িত।

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


2

গতিশীল ভাষায় টিপলের মতো কিছু করতে পারে (পাইথন)

public class Tuple {
private Object[] multiReturns;

private Tuple(Object... multiReturns) {
    this.multiReturns = multiReturns;
}

public static Tuple _t(Object... multiReturns){
    return new Tuple(multiReturns);
}

public <T> T at(int index, Class<T> someClass) {
    return someClass.cast(multiReturns[index]);
}
}

এবং এই মত ব্যবহার করুন

public Tuple returnMultiValues(){
   return Tuple._t(new ArrayList(),new HashMap())
}


Tuple t = returnMultiValues();
ArrayList list = t.at(0,ArrayList.class);

2

আমি আমার প্রয়োজন অনুসারে কয়েকটি টুইটের সাথে অন্যান্য জবাবগুলিতে বর্ণিত বর্ণনার তুলনায় অনুরূপ পন্থা অনুসরণ করেছি, মূলত আমি নিম্নলিখিত ক্লাসগুলি তৈরি করেছি (ঠিক তেমন, সবকিছুই জাভা):

public class Pair<L, R> {
    final L left;
    final R right;

    public Pair(L left, R right) {
        this.left = left;
        this.right = right;
    }

    public <T> T get(Class<T> param) {
        return (T) (param == this.left.getClass() ? this.left : this.right);
    }

    public static <L, R> Pair<L, R> of(L left, R right) {
        return new Pair<L, R>(left, right);
    }
}

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

সুতরাং, উদাহরণস্বরূপ, আমার পদ্ধতিগুলি এরকম:

public Pair<ResultMessage, List<Customer>> getCustomers() {
    List<Customer> list = new ArrayList<Customer>();
    try {
    /*
    * Do some work to get the list of Customers from the DB
    * */
    } catch (SQLException e) {
        return Pair.of(
                       new ResultMessage(e.getErrorCode(), e.getMessage()), // Left 
                       null);  // Right
    }
    return Pair.of(
                   new ResultMessage(0, "SUCCESS"), // Left 
                   list); // Right
}

যেখানে রেজাল্টমেজেজ কেবলমাত্র দুটি ক্ষেত্র (কোড / বার্তা) সহ একটি ক্লাস এবং গ্রাহক ডিবি থেকে আসে এমন একগুচ্ছ ক্ষেত্র সহ কোনও শ্রেণি।

তারপরে, ফলাফলটি পরীক্ষা করতে আমি কেবল এটি করি:

void doSomething(){
    Pair<ResultMessage, List<Customer>> customerResult = _repository.getCustomers();
    if (customerResult.get(ResultMessage.class).getCode() == 0) {
        List<Customer> listOfCustomers = customerResult.get(List.class);
        System.out.println("do SOMETHING with the list ;) ");
    }else {
        System.out.println("Raised Error... do nothing!");
    }
}

1

সি ++ (এসটিএল) এ দুটি বস্তু বান্ডিল করার জন্য একটি জোড় শ্রেণি রয়েছে। জাভা জেনেরিক্সে একটি জোড়া ক্লাস উপলব্ধ নয়, যদিও এর জন্য কিছু চাহিদা রয়েছে । আপনি সহজেই এটি প্রয়োগ করতে পারেন।

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


1

WhateverFunctionResultআপনার ফলাফলগুলি অন্তর্ভুক্ত করে এমন কোনও বস্তু কেন তৈরি করবেন না এবং এই ফলাফলগুলি বিশ্লেষণের জন্য প্রয়োজনীয় যুক্তি, তারপরে পুনরাবৃত্তি করা ইত্যাদি It এটা আমার কাছে মনে হয়:

  1. এই ফলাফলের বিষয়গুলি নিবিড়ভাবে বেঁধে দেওয়া / সম্পর্কিত এবং একত্রে সম্পর্কিত, বা:
  2. এগুলি সম্পর্কিত নয়, এক্ষেত্রে আপনার ফাংশন এটি করার চেষ্টা করছে (যেমন দুটি পৃথক কাজ করা) এর ক্ষেত্রে তার সংজ্ঞা দেওয়া হয়নি case

আমি বারবার এই ধরণের ইস্যু ক্রপটি দেখতে পাচ্ছি। আপনার নিজের ধারক / ফলাফল শ্রেণি তৈরি করতে ভয় পাবেন না যাতে এটি পরিচালনা করতে ডেটা এবং সম্পর্কিত কার্যকারিতা থাকে Don't আপনি যদি স্টাফটি কেবল কোনও HashMapবা অনুরূপভাবে পাস করেন তবে আপনার ক্লায়েন্টদের এই মানচিত্রটি আলাদা করে রাখতে হবে এবং প্রতিবার ফলাফলগুলি ব্যবহার করতে চাইলে সামগ্রীগুলি ছাঁটাইতে হবে।


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

1
public class MultipleReturnValues {

    public MultipleReturnValues() {
    }

    public static void functionWithSeveralReturnValues(final String[] returnValues) {
        returnValues[0] = "return value 1";
        returnValues[1] = "return value 2";
    }

    public static void main(String[] args) {
        String[] returnValues = new String[2];
        functionWithSeveralReturnValues(returnValues);
        System.out.println("returnValues[0] = " + returnValues[0]);
        System.out.println("returnValues[1] = " + returnValues[1]);
    }

}

1

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

কেস এক।

আপনার পদ্ধতির বাইরের পাশাপাশি আপনার ভিতরেও কিছু দরকার। কেন এটি বাইরে গণনা করে তা পদ্ধতিতে পাস করবেন না?

পরিবর্তে:

[thingA, thingB] = createThings(...);  // just a conceptual syntax of method returning two values, not valid in Java

চেষ্টা করুন:

thingA = createThingA(...);
thingB = createThingB(thingA, ...);

এটি আপনার বেশিরভাগ চাহিদা আবরণ করা উচিত, যেহেতু বেশিরভাগ পরিস্থিতিতে একটি মান অন্যটির আগে তৈরি হয় এবং আপনি এগুলি দুটি পদ্ধতিতে তৈরি করে বিভক্ত করতে পারেন। ত্রুটিটি হ'ল সেই পদ্ধতির createThingsBসাথে তুলনা করার একটি অতিরিক্ত প্যারামিটার রয়েছে createThingsএবং সম্ভবত আপনি প্যারামিটারগুলির একই তালিকাটি বিভিন্ন পদ্ধতিতে দু'বার পার করছেন।


কেস দুই।

সর্বকালের সবচেয়ে সুস্পষ্ট সমাধান এবং একের এক সহজ সংস্করণ। এটি সবসময় সম্ভব না, তবে উভয় মান একে অপরের থেকে স্বাধীনভাবে তৈরি করা যেতে পারে?

পরিবর্তে:

[thingA, thingB] = createThings(...);  // see above

চেষ্টা করুন:

thingA = createThingA(...);
thingB = createThingB(...);

আরও কার্যকর করার জন্য, এই দুটি পদ্ধতিতে কিছু সাধারণ যুক্তি ভাগ করা যায়:

public ThingA createThingA(...) {
    doCommonThings(); // common logic
    // create thing A
}
public ThingB createThingB(...) {
    doCommonThings(); // common logic
    // create thing B
}

0

আপনার পদ্ধতিতে একটি তালিকা পাস করুন এবং এটিকে জনপ্রিয় করুন, তারপরে নামগুলি সহ স্ট্রিংটি ফিরে দিন:

public String buildList(List<?> list) {
    list.add(1);
    list.add(2);
    list.add(3);
    return "something,something,something,dark side";
}

তারপরে এটিকে কল করুন:

List<?> values = new ArrayList<?>();
String names = buildList(values);

-2

আমি একাধিক রিটার্নের সমস্যার সাথে মোকাবিলা করার জন্য একটি খুব প্রাথমিক পদ্ধতির ব্যবহার করছি। এটি উদ্দেশ্যটি সরবরাহ করে এবং জটিলতা এড়ায়।

আমি এটিকে স্ট্রিং বিভাজক বলি অ্যাপ্রোচ

এবং এটি কার্যকর কারণ এটি একাধিক প্রকারের মানগুলিও ফিরিয়ে দিতে পারে যেমন int, ডাবল, চর, স্ট্রিং ইত্যাদিও

এই পদ্ধতির মধ্যে আমরা একটি স্ট্রিং ব্যবহার করি যা সাধারণভাবে হওয়ার সম্ভাবনা খুব কম। আমরা একে বিভাজক হিসাবে ডাকি। এই বিভাজক একটি ফাংশনে ব্যবহৃত হয় যখন বিভিন্ন মান পৃথক করতে ব্যবহৃত হবে

উদাহরণস্বরূপ, আমাদের চূড়ান্ত রিটার্ন হবে (উদাহরণস্বরূপ) ইনটাল্যু বিভাজক ডাবলভ্যালু বিভাজক ... এবং তারপরে এই স্ট্রিংটি ব্যবহার করে আমরা প্রয়োজনীয় সমস্ত তথ্য পুনরুদ্ধার করব, এটি বিভিন্ন ধরণেরও হতে পারে

নিম্নলিখিত কোডটি এই ধারণার কাজ দেখায়

বিভাজকটি ব্যবহৃত হয় ! @ # এবং 3 টি মানগুলি ইনটওয়াল, ডাবলভাল এবং স্ট্রিংওয়াল ফিরছে

        public class TestMultipleReturns {

            public static String multipleVals() {

                String result = "";
                String separator = "!@#";


                int intVal = 5;
                // Code to process intVal

                double doubleVal = 3.14;
                // Code to process doubleVal

                String stringVal = "hello";
                // Code to process Int intVal

                result = intVal + separator + doubleVal + separator + stringVal + separator;
                return (result);
            }

            public static void main(String[] args) {

                String res = multipleVals();

                int intVal = Integer.parseInt(res.split("!@#")[0]);
                // Code to process intVal

                double doubleVal = Double.parseDouble(res.split("!@#")[1]);
                // Code to process doubleVal

                String stringVal = res.split("!@#")[2];

                System.out.println(intVal+"\n"+doubleVal+"\n"+stringVal);
            }
        }

আউটপুট

5
3.14
hello
BUILD SUCCESSFUL (total time: 2 seconds)

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

-4

সি-তে, আপনি ফলাফলের জন্য স্থানধারকদের কাছে যুক্তি হিসাবে পয়েন্টার পাঠিয়ে এটি করবেন:

void getShoeAndWaistSizes(int *shoeSize, int *waistSize) {
    *shoeSize = 36;
    *waistSize = 45;
}
...
int shoeSize, waistSize;
getShoeAndWaistSize(&shoeSize, &waistSize);
int i = shoeSize + waistSize;

আসুন জাভাতেও অনুরূপ কিছু চেষ্টা করি।

void getShoeAndWaistSizes(List<Integer> shoeSize, List<Integer> waistSize) {
    shoeSize.add(36);
    waistSize.add(45);
}
...
List<Integer> shoeSize = new List<>();
List<Integer> waistSize = new List<>();
getShoeAndWaistSizes(shoeSize, waistSize);
int i = shoeSize.get(0) + waistSize.get(0);

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

@ টুলমেকারস্টেটিভ স্পষ্ট করে বলতে: তালিকাগুলির প্রতিটিটির জন্য সঠিকভাবে একটি উপাদান রয়েছে এবং পাস-বাই-পয়েন্টারটির জন্য একটি অ্যানালগ প্রয়োগ করার কেবলমাত্র একটি উপায়। এগুলি বেশ কয়েকটি ফলাফল সংগ্রহ করার উদ্দেশ্যে নয়, এমনকি পদ্ধতি কলের পরে কয়েকটি লাইন ছাড়াও ব্যবহৃত হবে।
অ্যাড্রিয়ান পানাসিয়ুক

-5

পদ্ধতির মধ্যে একটি হ্যাশ পাস এবং এটি জনপ্রিয় করুন ......

সর্বজনীন শূন্য বিল্ড রেসপোনস (স্ট্রিং ডেটা, মানচিত্রের প্রতিক্রিয়া);

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