উপাদান হিসাবে নিজেকে থাকা অ্যারেলিস্টের হ্যাশ কোড


38

আমরা কি এমন hashcodeএকটি আবিষ্কার করতে পারি listযা এতে নিজেকে থাকে element?

আমি জানি এটি একটি খারাপ অভ্যাস, তবে সাক্ষাত্কারকারীর এটিই বলেছিল।

যখন আমি নিম্নলিখিত কোডটি চালিত করি এটি একটি নিক্ষেপ করে StackOverflowError:

public class Main {
    public static void main(String args[]) {
        ArrayList<ArrayList> a = new ArrayList();
        a.add(a);
        a.hashCode();
    }
}

এখন এখানে আমার দুটি প্রশ্ন আছে:

  1. সেখানে কেন StackOverflowError?
  2. এভাবে কি হ্যাশ কোডটি পাওয়া সম্ভব?

7
কারণ আপনি তালিকাটি নিজেরাই যুক্ত করেন। অ্যাড স্টেটমেন্ট ছাড়াই a.hashCode () চেষ্টা করুন
জেনস

আপনি যখন কোনও বস্তুকে একটি অ্যারেলিস্টে রাখবেন তখন আপনি বস্তুর রেফারেন্সটি সংরক্ষণ করছেন your আপনার ক্ষেত্রে আপনি একটি অ্যারেলিস্ট জাদুকরী রাখছেন তা নিজেই রেফারেন্স।
বিশ্বরত্ন


ঠিক আছে, আমি কেন পেয়েছি কেন স্ট্যাকওভারফ্লো আছে, কেউ কেউ আমাকে সমস্যা নম্বর 2- টি ব্যাখ্যা করতে সহায়তা করতে পারে- এটি কীভাবে খুঁজে পাবেন
জোকার

9
অন্যরা যেমন উত্তর দিয়েছে, Listইন্টারফেসের খুব সংজ্ঞা দিয়ে এটি সম্ভব নয়, hashCodeএকটি তালিকার তালিকা তার সদস্যদের উপর নির্ভর করে। তালিকাটি তার নিজস্ব সদস্য হিসাবে দেওয়া হয়েছে, এটির হ্যাশ কোড তার উপর নির্ভর করে hashCode, যা এর hashCode... এবং এর উপর নির্ভর করে, অসীম পুনরাবৃত্তি ঘটায় এবং StackOverflowErrorআপনি যার মধ্যে চলেছেন । এখন প্রশ্ন হ'ল: কেন নিজেকে অন্তর্ভুক্ত রাখতে একটি তালিকা প্রয়োজন? আমি আপনাকে গ্যারান্টি দিতে পারি যে এটির মতো পুনরাবৃত্ত সদস্যতার প্রয়োজন ছাড়াই আপনি আরও ভাল উপায়ে যা করার চেষ্টা করছেন তা অর্জন করতে পারবেন।
আলেকজান্ডার - মনিকা 18

উত্তর:


36

Listবাস্তবায়ন অনুসারে হ্যাশ কোডটি ইন্টারফেসে নির্দিষ্ট করা হয়েছে :

এই তালিকার জন্য হ্যাশ কোড মান প্রদান করে। একটি তালিকার হ্যাশ কোডটি নিম্নলিখিত গণনার ফলাফল হিসাবে সংজ্ঞায়িত করা হয়েছে:

 int hashCode = 1;
 for (E e : list)
     hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

এটি নিশ্চিত করে যে list1.equals(list2)যে বোঝা list1.hashCode()==list2.hashCode()কোন দুটি তালিকার জন্য, list1এবং list2, যেমন সাধারণ চুক্তি দ্বারা প্রয়োজন Object.hashCode()

এর জন্য বাস্তবায়নটি ঠিক দেখতে দেখতে লাগে না (দেখুন বিকল্পের জন্য তালিকা.হ্যাশকোড () এর মতো একটি স্ট্রিমের জন্য হ্যাশ কোডটি কীভাবে গণনা করা যায় ) তবে কেবলমাত্র নিজের তালিকাভুক্ত তালিকার জন্য সঠিক হ্যাশ কোডটি হবে এমন একটি সংখ্যা হতে x == 31 + xহবে যার জন্য অবশ্যই true, অন্য কথায়, একটি মানিয়ে নেওয়া সংখ্যা গণনা করা অসম্ভব।


1
@Holger, Eirc সমগ্র ফাংশন কোড প্রতিস্থাপন করতে চায় hashCode()রিটার্ন 0। এটি প্রযুক্তিগতভাবে সমাধান x == 31 + xকরে তবে প্রয়োজনীয়তাটিকে উপেক্ষা করে যে এক্স অবশ্যই কমপক্ষে 1 হতে হবে
বিএক্সকে 21

4
@ এরিকডুমিনিল আমার উত্তরের বিষয়টি হ'ল, চুক্তিতে একটি যুক্তি বর্ণিত হয়েছে যা ArrayListআক্ষরিক অর্থে প্রয়োগ করে, যা পুনরাবৃত্তির দিকে পরিচালিত করে, তবে বিকল্পের বাস্তবায়নও হয় না। নোট করুন যে আমি আমার উত্তরটি এমন সময়ে পোস্ট করেছি যখন ওপি ইতিমধ্যে বুঝতে পেরেছিল যে এই নির্দিষ্ট প্রয়োগটি কেন একটি দিকে পরিচালিত করে StackOverflowError, যা অন্য উত্তরে সম্বোধন করা হয়েছে। সুতরাং আমি একটি মান দিয়ে সীমাবদ্ধ সময়ে সমাপ্তি বাস্তবায়নের সাধারণ অসম্ভবতার দিকে মনোনিবেশ করেছি।
হলগার

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

2
@ পিডিএম আপনি এটি বিপরীত করছেন। আমি কখনও বলিনি যে হ্যাশ কোডের কারণে তালিকাটি সমান হতে হবে। তালিকা হয় , সমান সংজ্ঞা দ্বারা। Arrays.asList("foo")সমান Collections.singletonList("foo"), সমান হয় List.of("foo")সমান new ArrayList<>(List.of("foo"))। এই সমস্ত তালিকা সমান, পয়েন্ট। তারপরে, এই তালিকাগুলি সমান হওয়ায় তাদের অবশ্যই একই হ্যাশ কোড থাকা উচিত। অন্য রাস্তা নয়। যেহেতু তাদের অবশ্যই একই হ্যাশ কোড থাকতে হবে, এটি অবশ্যই ভাল সংজ্ঞাযুক্ত। তারা এটি কীভাবে সংজ্ঞায়িত করেছে (জাভা 2 এ ফিরে) তা নির্ধারণ করা উচিত, সমস্ত বাস্তবায়ন দ্বারা সম্মতি জানাতে হবে।
হোলার

2
@pdem ঠিক, একটি কাস্টম বাস্তবায়ন যেগুলি হয়, বাস্তবায়ন নেই Listবা বড় সতর্কবার্তা সাইন, সঙ্গে তুলনা "সাধারণ তালিকা সঙ্গে মিশ্রিত করা না" হয়েছে IdentityHashMapএবং তার " এই বর্গ না একটি সাধারণ ম্যাপ বাস্তবায়ন! ”সতর্কতা প্রাক্তন ক্ষেত্রে, আপনি ইতিমধ্যে কার্যকর Collectionকরার সাথে সাথে তালিকার শৈলীর সূচক ভিত্তিক অ্যাক্সেস পদ্ধতি যুক্ত করার ক্ষেত্রে ইতিমধ্যে ভাল। তারপরে, কোনও সাম্যের সীমাবদ্ধতা বিদ্যমান নেই, তবে এটি এখনও অন্যান্য সংগ্রহের ধরণের সাথে সুচারুভাবে কাজ করে।
হোলার

23

ক্লাসে hashCodeপদ্ধতিটির কঙ্কালের বাস্তবায়ন পরীক্ষা করে দেখুন AbstractList

public int hashCode() {
    int hashCode = 1;
    for (E e : this)
        hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    return hashCode;
}

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


তাহলে উত্তরটি কি এইভাবে হ্যাশ কোডটি খুঁজে পাওয়ার কোনও উপায় নেই?
জোকার

3
হ্যাঁ, পুনরাবৃত্তির শর্তের কারণে
স্প্রিজ করুন

শুধু তাই নয়, এটি এইভাবে সংজ্ঞায়িত করা হয়েছে
ক্রিলিস-হরতাল-

14

আপনি একটি (প্যাথলজিকাল) তালিকা সংজ্ঞায়িত করেছেন যা এতে রয়েছে।

কেন আছে StackOverflowError?

মতে javadocs (স্পেসিফিকেশন অর্থাৎ), একটি এর হ্যাশকোড Listতার উপাদানের প্রতিটি হ্যাশকোড একটি ফাংশন সংজ্ঞায়িত করা হয়। এটা বলে:

"একটি তালিকার হ্যাশ কোডটি নিম্নলিখিত গণনার ফলাফল হিসাবে সংজ্ঞায়িত করা হয়েছে:"

int hashCode = 1;
    for (E e : list)
         hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

সুতরাং এর হ্যাশকোড গণনা করতে a, আপনি প্রথমে এর হ্যাশকোড গণনা a। এটি অসীম পুনরাবৃত্তিযোগ্য এবং দ্রুত স্ট্যাকের ওভারফ্লোতে নিয়ে যায়।

এইভাবে কি হ্যাশ কোডটি পাওয়া সম্ভব?

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


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

1
@ নেট কিছু ব্যবহারকারী কেবল শীর্ষে উত্তরগুলি পড়েন।
হলগার

8

না, ডকুমেন্টেশনের একটি উত্তর আছে

তালিকা কাঠামো ডকুমেন্টেশন স্পষ্টভাবে বলে:

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

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


1
এটি নির্দিষ্টকরণের বাইরে কেন আপনি বলেছিলেন তাই এটি ব্যাখ্যা করে যে এটি কোনও বাগ নয়। এটি অন্যান্য উত্তর থেকে অনুপস্থিত অংশ ছিল।
পিডিএম

3

রবীন্দ্রের উত্তরটি ১ ম পয়েন্টের জন্য একটি ভাল ব্যাখ্যা দেয় question প্রশ্ন 2 তে মন্তব্য করতে:

এইভাবে কি হ্যাশ কোডটি পাওয়া সম্ভব?

কিছু এখানে বিজ্ঞপ্তি হয়। এই স্ট্যাক ওভারফ্লো ত্রুটির প্রসঙ্গে এই 2 টির মধ্যে কমপক্ষে একটিতে অবশ্যই ভুল হতে হবে:

  • তালিকার হ্যাশ কোডটি অবশ্যই এর উপাদানগুলির মধ্যে থাকা উচিত
  • এটি কোনও তালিকার নিজস্ব উপাদান হিসাবে ঠিক আছে

এখন, যেহেতু আমরা কোনওটির সাথে কাজ করছি ArrayList, প্রথম পয়েন্টটি স্থির হয়েছে। অন্য কথায়, সম্ভবত আপনার পুনরাবৃত্তির তালিকার একটি হ্যাশ কোডটি অর্থপূর্ণভাবে গণনা করতে সক্ষম হওয়ার জন্য আপনার আলাদা বাস্তবায়ন প্রয়োজন ... একটি ArrayListউপাদানগুলির হ্যাশ কোডগুলি যুক্ত করতে বাড়াতে পারে, এর মতো কিছু something

for (E e : this)
  if(e == this) continue; //contrived rules
  hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

পরিবর্তে যেমন একটি বর্গ ব্যবহার করে ArrayList, আপনি পারে।

সাথে ArrayList, দ্বিতীয় পয়েন্টটি ভুল। সুতরাং যদি সাক্ষাত্কারটির অর্থ "কী এইভাবে (অ্যারের তালিকার সাথে) হ্যাশ কোডটি পাওয়া সম্ভব?" , তবে উত্তরটি হ'ল না কারণ এটি অযৌক্তিক।


1
হ্যাশ কোড হিসাব দ্বারা বাধ্যতামূলক করা হয় চুক্তি । কোনও বৈধ বাস্তবায়ন নিজেই এড়িয়ে যেতে পারে না। স্পেসিফিকেশন থেকে, আপনি আহরণ করতে পারে আপনি একটি খুঁজে পান, তাহলে সংখ্যা, যার জন্য হয় , তাহলে আপনি একটি বৈধ ছোট করে কাটা ... বাস্তবায়ন করতে পারেListintx == 31 + xtrue
হোলগার

@ হোলজার কী বলছে তা আমি পুরোপুরি বুঝতে পারি নি। তবে সমাধানে 2 টি সমস্যা রয়েছে: প্রথম: এটি কেবল তখনই সমস্যা সমাধান করে যখন এই তালিকাটি নিজের আইটেম এবং যদি তালিকাটি না থাকে তবে নিজের আইটেমের একটি আইটেম (পুনরাবৃত্তির গভীর স্তর) দ্বিতীয়: যদি তালিকাটি নিজেই এড়িয়ে যায় খালি তালিকার সমান হতে পারে।
জোনাস মিশেল

1
স্থাপিত টুইট আমি শুধু দার্শনিকভাবে 2. প্রশ্নই অর্থহীনতা প্রায় ডিবেটিং করছি আমরা যদি উচিত নয় যেমন একটি তালিকার জন্য একটি হ্যাশ কোড গনা, তাহলে এটি কাজ যদি না আমরা একটি অ্যারের তালিকা (এবং হোলগার বাড়িয়ে তোলে এর বাধ্যতা সরাবে না বলে যে দ্বারা Listআনুষ্ঠানিকভাবে নির্দেশনা হ্যাশ কোড যুক্তিবিজ্ঞান বাস্তবায়নের দ্বারা মেনে করা হবে)
ernest_k

আমার (সীমাবদ্ধ) বোধগম্যতা Listহ্যাশ কোড গণনা সরবরাহ করে তবে আমরা এটিকে ওভাররাইড করতে পারি। একমাত্র আসল প্রয়োজনীয়তা হ্যাশকোডগুলির সাধারণ হ'ল: যদি বস্তুগুলি সমান হয় তবে হ্যাশকোডগুলি সমান হতে হবে। এই বাস্তবায়ন সেই প্রয়োজন অনুসরণ করে।
তিপিম্ম

1
@ টিপিম Listএকটি ইন্টারফেস। এটি একটি চুক্তি সংজ্ঞায়িত করে, এটি কোনও বাস্তবায়ন সরবরাহ করে না । অবশ্যই, চুক্তিটি সমতা এবং হ্যাশ কোড উভয়কেই কভার করে। যেহেতু সমতার সাধারণ চুক্তিটি এটি প্রতিসম হতে হবে, আপনি যদি একটি তালিকার প্রয়োগ বাস্তবায়ন করেন তবে আপনাকে সমস্ত বিদ্যমান তালিকা বাস্তবায়ন পরিবর্তন করতে হবে, অন্যথায়, আপনি এমনকি এর মৌলিক চুক্তিটি ভঙ্গ করবেন java.lang.Object
হলগার

1

কারণ আপনি যখন একই ফাংশন থেকে একই ফাংশনটি কল করবেন তখন এটি পুনরাবৃত্তির শর্ত তৈরি করবে যা কখনই শেষ হয় না। এবং এই অপারেশন প্রতিরোধ করতে JAVA ফিরে আসবেjava.lang.StackOverflowError

নীচে উদাহরণ কোড দেওয়া যা অনুরূপ দৃশ্যের ব্যাখ্যা দেয়:

public class RefTest {

    public static void main(String... strings) {
        RefTest rf = new RefTest();
        rf.message(message("test"));
    }

    public static String message2(String s){
        return message(s);
    }

    public static String message(String s){
        return message2(s);
    }

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