বিপরীত অনুসন্ধানের সাথে জাভাতে কি হ্যাশম্যাপ রয়েছে?


98

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

আমি আমার নিজের ক্লাসটি লিখতে পারি যা মূলত দুটি মিররযুক্ত মানচিত্র ব্যবহার করে তবে আমি চাকাটি পুনরায় উদ্ভাবন করব না (যদি এটি ইতিমধ্যে বিদ্যমান তবে আমি কেবল সঠিক শব্দটির সন্ধান করছি না)।

উত্তর:


107

জাভা এপিআইতে এ জাতীয় কোনও শ্রেণি নেই। আপনি যে অ্যাপাচি কমন্স ক্লাসটি চান তা বিড়িম্যাপের অন্যতম বাস্তবায়ন হতে চলেছে

একজন গণিতবিদ হিসাবে আমি এই ধরণের কাঠামোটিকে বাইজেকশন বলব।


84
একজন অ-গণিতবিদ হিসাবে আমি এই ধরণের কাঠামোটিকে "একটি মানচিত্র বলে যা আপনাকে কী বা অন্যান্য উপায়ে মূল্যায়ন করতে দেয়" বলবে
ডানাল

4
খুব খারাপ এটির জেনারিকদের পক্ষে কোনও সমর্থন নেই, মনে হয় পেয়ারা করেন।
ইরান মেদান

4
github.com/megamattron/col લેક્- জেনেরিক জেনারিক্স সমর্থন সঙ্গে বিডিম্যাপ আছে
কেনস্টন চোই

4
@ দান "বিড়ি" -> "দ্বি-দিকনির্দেশক"
স্বেচ্ছাসেবক

4
@ ডোনাল হ্যাঁ, তবে পুরো আইটি গণিতের উপর ভিত্তি করে
অ্যালেক্স

77

এ্যাপাচি কমন্স ছাড়াও, পেয়ারা একটি হয়েছে BiMap


তথ্যের জন্য ধন্যবাদ! আমি
কিপ

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

16
গুগল সংগ্রহের একটি সুবিধা হ'ল এর জেনারিকস রয়েছে যেখানে কমন্স সংগ্রহগুলি নেই।
চিহ্নিত করুন

4
দুটি লিবের তুলনা করার জন্য, এই উত্তরের উদ্ধৃতিগুলি দেখুন: স্ট্যাকওভারফ্লো.com / প্রশ্নস / 74787474464646 / (এবং মূল সাক্ষাত্কার)। এটি গুগলের প্রতি পক্ষপাতদুষ্ট, সুস্পষ্ট কারণে, তবে তবুও আমি আজকাল গুগল সংগ্রহের সাথে আরও ভাল বলে রাখা নিরাপদ বলে মনে করি।
জোনিক

4
বিম্যাপ লিংকটি নষ্ট হয়ে গেছে। ব্যবহার করুন এই এক
মাহসা 2

20

এটি সম্পন্ন করতে এখানে আমি ব্যবহার করি এমন একটি সাধারণ ক্লাস (আমি আর একটি তৃতীয় পক্ষের নির্ভরতা পেতে চাইনি)। এটি মানচিত্রে উপলব্ধ সমস্ত বৈশিষ্ট্য সরবরাহ করে না তবে এটি একটি ভাল শুরু start

    public class BidirectionalMap<KeyType, ValueType>{
        private Map<KeyType, ValueType> keyToValueMap = new ConcurrentHashMap<KeyType, ValueType>();
        private Map<ValueType, KeyType> valueToKeyMap = new ConcurrentHashMap<ValueType, KeyType>();

        synchronized public void put(KeyType key, ValueType value){
            keyToValueMap.put(key, value);
            valueToKeyMap.put(value, key);
        }

        synchronized public ValueType removeByKey(KeyType key){
            ValueType removedValue = keyToValueMap.remove(key);
            valueToKeyMap.remove(removedValue);
            return removedValue;
        }

        synchronized public KeyType removeByValue(ValueType value){
            KeyType removedKey = valueToKeyMap.remove(value);
            keyToValueMap.remove(removedKey);
            return removedKey;
        }

        public boolean containsKey(KeyType key){
            return keyToValueMap.containsKey(key);
        }

        public boolean containsValue(ValueType value){
            return keyToValueMap.containsValue(value);
        }

        public KeyType getKey(ValueType value){
            return valueToKeyMap.get(value);
        }

        public ValueType get(KeyType key){
            return keyToValueMap.get(key);
        }
    }

5
আপনিTKKYMap.containsKey (মান)
জেটিতে

আমি বর্তমানে এই মানচিত্রটি ব্যবহার করব না কারণ বর্তমানে দ্বি-দিকনির্দেশ ভেঙে যদি কোনও কী (বা মান) আলাদা মান (বা কী) দিয়ে পুনরায় যুক্ত করা হয় যা কোনও আইএমও আপডেট করার জন্য বৈধ ব্যবহার হবে।
Qw3ry

11

যদি কোনও সংঘর্ষ না ঘটে, আপনি সর্বদা একই হ্যাশম্যাপে উভয় দিক যুক্ত করতে পারেন :-)


6
@ কিপ: কেন? কিছু প্রসঙ্গে এটি একটি সম্পূর্ণ বৈধ সমাধান। সুতরাং দুটি হ্যাশ মানচিত্র থাকবে।
লরেন্স ডল

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

4
@ কিপ, আমি সম্মতি দিচ্ছি যে এই ব্যবহারটি সেই মানচিত্রটি ব্যবহার করে শ্রেণীর অভ্যন্তরীণ রাখা উচিত, তবে আপনার শেষ মন্তব্যটি কেবল তখনই সত্য হয় যদি সংশ্লিষ্ট জুনিয়ট পরীক্ষাগুলি
খসড়া হয়

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

একটি ছোট স্কেল দেখার জন্য, যে হ্যাক আমার সমস্যা সমাধান করে।
মিল্কার্সারাক

5

এখানে আমার 2 সেন্ট।

অথবা আপনি জেনেরিক সহ একটি সাধারণ পদ্ধতি ব্যবহার করতে পারেন। খুবই সহজ.

public static <K,V> Map<V, K> invertMap(Map<K, V> toInvert) {
    Map<V, K> result = new HashMap<V, K>();
    for(K k: toInvert.keySet()){
        result.put(toInvert.get(k), k);
    }
    return result;
}

অবশ্যই আপনার কাছে অনন্য মান সহ একটি মানচিত্র থাকতে হবে। অন্যথায়, তাদের মধ্যে একটি প্রতিস্থাপন করা হবে।


1

গীতার উত্তর দ্বারা অনুপ্রাণিত হয়ে আমি কিছু উন্নতি করে নিজেই অনুরূপ কিছু লেখার সিদ্ধান্ত নিয়েছি:

  • ক্লাস বাস্তবায়ন করছে Map<K,V>শ্রেণিটি ইন্টারফেসটি
  • একটি দ্বারা কোনও মান পরিবর্তন করার সময় এটির যত্ন নিয়ে দ্বিপাক্ষিকতাটি সত্যই গ্যারান্টিযুক্ত put(কমপক্ষে আমি এটির গ্যারান্টি দিয়ে আশা করি)

ম্যাপিং কলটিতে বিপরীত দর্শন পেতে ব্যবহার হ'ল সাধারণ মানচিত্রের মতো getReverseView() । সামগ্রীটি অনুলিপি করা হয় নি, শুধুমাত্র একটি দর্শন ফিরে আসে।

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

public class BidirectionalMap<Key, Value> implements Map<Key, Value> {

    private final Map<Key, Value> map;
    private final Map<Value, Key> revMap;

    public BidirectionalMap() {
        this(16, 0.75f);
    }

    public BidirectionalMap(int initialCapacity) {
        this(initialCapacity, 0.75f);
    }

    public BidirectionalMap(int initialCapacity, float loadFactor) {
        this.map = new HashMap<>(initialCapacity, loadFactor);
        this.revMap = new HashMap<>(initialCapacity, loadFactor);
    }

    private BidirectionalMap(Map<Key, Value> map, Map<Value, Key> reverseMap) {
        this.map = map;
        this.revMap = reverseMap;
    }

    @Override
    public void clear() {
        map.clear();
        revMap.clear();
    }

    @Override
    public boolean containsKey(Object key) {
        return map.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return revMap.containsKey(value);
    }

    @Override
    public Set<java.util.Map.Entry<Key, Value>> entrySet() {
        return Collections.unmodifiableSet(map.entrySet());
    }

    @Override
    public boolean isEmpty() {
        return map.isEmpty();
    }

    @Override
    public Set<Key> keySet() {
        return Collections.unmodifiableSet(map.keySet());
    }

    @Override
    public void putAll(Map<? extends Key, ? extends Value> m) {
        m.entrySet().forEach(e -> put(e.getKey(), e.getValue()));
    }

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public Collection<Value> values() {
        return Collections.unmodifiableCollection(map.values());
    }

    @Override
    public Value get(Object key) {
        return map.get(key);
    }

    @Override
    public Value put(Key key, Value value) {
        Value v = remove(key);
        getReverseView().remove(value);
        map.put(key, value);
        revMap.put(value, key);
        return v;
    }

    public Map<Value, Key> getReverseView() {
        return new BidirectionalMap<>(revMap, map);
    }

    @Override
    public Value remove(Object key) {
        if (containsKey(key)) {
            Value v = map.remove(key);
            revMap.remove(v);
            return v;
        } else {
            return null;
        }
    }

}

মনে রাখবেন যে বিম্যাপ এবং বিডিম্যাপ যেমন ঠিক তেমন, এটি এমন একটি বাইজিকেশন যা একই মান সহ একাধিক কী রাখার অনুমতি দেয় না। (getReversView ()। get (v) সর্বদা কেবল একটি কী ফেরত দেবে)।
ডোনাটেলো

সত্য, তবে
ওটিও এইচপি

আমি নিশ্চিত নই যে তিনি প্রকাশ করেছেন যে এর ডেটা এই সীমাবদ্ধতার সাথে মিলেছে, তবে যাইহোক, এটি অন্য কাউকে আরও ভালভাবে বুঝতে সাহায্য করতে পারে!
দোনেটেলো

0

এখানে বেশ পুরানো প্রশ্ন, তবে অন্য কারও যদি মস্তিষ্কের অবরুদ্ধ থাকে যেমন আমি ঠিক করেছি এবং এতে হোঁচট খেয়েছি, আশা করি এটি সাহায্য করবে।

আমিও দ্বি-দিকনির্দেশক হ্যাশম্যাপের সন্ধান করছিলাম, কখনও কখনও এটি উত্তরগুলির সর্বাধিক দরকারী যা সর্বাধিক দরকারী।

আপনি যদি চাকাটি পুনরায় উদ্ভাবন করতে না চান এবং আপনার প্রকল্পে অন্যান্য গ্রন্থাগার বা প্রকল্পগুলি যুক্ত না করতে পছন্দ করেন, তবে কীভাবে সমান্তরাল অ্যারেগুলির একটি সাধারণ বাস্তবায়ন (বা আপনার নকশার দাবি থাকলে অ্যারেলিস্টস) how

SomeType[] keys1 = new SomeType[NUM_PAIRS];
OtherType[] keys2 = new OtherType[NUM_PAIRS];

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

SomeType getKey1(OtherType ot);
SomeType getKey1ByIndex(int key2Idx);
OtherType getKey2(SomeType st); 
OtherType getKey2ByIndex(int key2Idx);

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


4
আপনি হ্যাশম্যাপসের একটি গুরুত্বপূর্ণ বৈশিষ্ট্য হারাচ্ছেন, যথা, হে (1) অনুসন্ধান। এর মতো প্রয়োগের জন্য আপনি যে আইটেমটি সন্ধান করছেন তার সূচক না পাওয়া পর্যন্ত অ্যারেগুলির মধ্যে একটির মাধ্যমে স্ক্যান করা প্রয়োজন
কিপ

হ্যাঁ এটি খুব সত্য এবং এটির পরিবর্তে এক বৃহত ব্যর্থতা। তবে আমার ব্যক্তিগত পরিস্থিতিতে আমি আসলে একটি ত্রি-দিকীয় কী তালিকার প্রয়োজনের সাথে মোকাবিলা করছিলাম এবং আমি সর্বদা সময়ের আগে কমপক্ষে 1 টি কী জানতাম, তাই ব্যক্তিগতভাবে আমার পক্ষে এটি কোনও সমস্যা ছিল না। যদিও এটি উল্লেখ করার জন্য আপনাকে ধন্যবাদ, আমি মনে করি এই গুরুত্বপূর্ণ সত্যটি আমার মূল পোস্টে এড়িয়ে গিয়েছি।
ThatOneGuy
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.