হ্যাশম্যাপে কী দেওয়া একটি মান কীভাবে আপডেট করবেন?


624

ধরুন HashMap<String, Integer>জাভাতে আমাদের একটা আছে।

আমি যে স্ট্রিংটি পেয়েছি তার প্রতিটি অস্তিত্বের জন্য স্ট্রিং-কীটির পূর্ণসংখ্যা-মান কীভাবে আপডেট করব (বৃদ্ধি)?

কেউ এই জুটিটি সরিয়ে এবং পুনরায় প্রবেশ করতে পারে তবে ওভারহেড একটি উদ্বেগের বিষয় হবে।
অন্য উপায়টি হ'ল নতুন জুটি রাখা এবং পুরানোটি প্রতিস্থাপন করা হবে।

পরবর্তী ক্ষেত্রে, যদি আমি একটি নতুন কী sertোকানোর চেষ্টা করছি তার সাথে যদি হ্যাশকোডের সংঘর্ষ হয় তবে কি হবে? হ্যাশটেবলের সঠিক আচরণ হ'ল এর জন্য আলাদা জায়গা বরাদ্দ করা বা বর্তমান বালতিতে এটির তালিকা তৈরি করা।

উত্তর:


970
map.put(key, map.get(key) + 1);

জরিমানা করা উচিত. এটি বিদ্যমান ম্যাপিংয়ের মান আপডেট করবে। মনে রাখবেন যে এটিতে অটো-বক্সিং ব্যবহার করা হয়েছে। map.get(key)আমরা যার সাহায্যে সংশ্লিষ্ট কীটির মান পাই, তারপরে আপনি আপনার প্রয়োজনীয়তার সাথে আপডেট করতে পারেন। এখানে আমি 1 দ্বারা ইনক্রিমেন্ট মান আপডেট করছি।


21
আসলে এটিই সবচেয়ে মজবুত এবং স্কেলযোগ্য এন্টারপ্রাইজ সমাধান।
লাভির দ্য হোয়লেটটি

12
@ লাভির, এটি কোনও খারাপ সমাধান নয়, তবে এটি সবচেয়ে শক্তিশালী এবং স্কেলযোগ্য কীভাবে তা দেখতে পান না। পরিবর্তে একটি পরমাণুবিজ্ঞানী অনেক বেশি স্কেলযোগ্য।
জন ভিন্ট

13
এই কী ধরে আছে, তাই না? আমি নালপয়েন্টার ব্যতিক্রম পাচ্ছি যখন তা হয় না।
ইয়ান

84
জাভা 8 এর সাহায্যে এটি সহজেই ব্যবহার করে এড়ানো যায় getOrDefault, উদাহরণস্বরূপ:map.put(key, count.getOrDefault(key, 0) + 1);
মার্টিন

2
@ মার্টিন .. মানচিত্র.পুট (কী, ম্যাপ.জিট ওআরডিফল্ট (কী, 0) + 1)
সত্যেশ

110

জাভা 8 উপায়:

আপনি computeIfPresentপদ্ধতিটি ব্যবহার করতে পারেন এবং এটিকে ম্যাপিং ফাংশন সরবরাহ করতে পারেন , যা বিদ্যমান মানের উপর ভিত্তি করে নতুন মান গণনা করার জন্য ডাকা হবে।

উদাহরণ স্বরূপ,

Map<String, Integer> words = new HashMap<>();
words.put("hello", 3);
words.put("world", 4);
words.computeIfPresent("hello", (k, v) -> v + 1);
System.out.println(words.get("hello"));

পর্যায়ক্রমে, আপনি mergeপদ্ধতিটি ব্যবহার করতে পারেন , যেখানে 1 হ'ল ডিফল্ট মান এবং ফাংশনটি বিদ্যমান মানকে 1 দ্বারা বৃদ্ধি করে:

words.merge("hello", 1, Integer::sum);

এ ছাড়াও অন্যান্য দরকারী পদ্ধতি, যেমন একটি গুচ্ছ হয় putIfAbsent, getOrDefault, forEach, ইত্যাদি


3
আমি স্রেফ আপনার সমাধানগুলি পরীক্ষা করেছি। দ্বিতীয়টি, পদ্ধতিটির উল্লেখ সহকারে একটি কাজ করে। প্রথম এক, ল্যামডা অভিব্যক্তি এক, ধারাবাহিকভাবে কাজ করছে না যখন আপনার মানচিত্রের কোনো মান null(বলুন words.put("hello", null);), ফলাফলের এখনও nullনা 1হিসাবে আমি আশা করবে।
তাও ঝাং

3
জাভাডোক থেকে: "যদি নির্দিষ্ট কীটির মান উপস্থিত থাকে এবং শূন্য হয় তবে একটি নতুন ম্যাপিং গণনা করার চেষ্টা করুন"। আপনি compute()পরিবর্তে ব্যবহার করতে পারেন , এটি মানগুলিও পরিচালনা করবে null
দামালুয়ার

আমি আমার মানটি ১ দ্বারা বাড়িয়ে দিতে চাই .mergeএটি আমার সমাধান Integer::sum
এস_কে

48
hashmap.put(key, hashmap.get(key) + 1);

পদ্ধতিটি একটি বিদ্যমান কীটির মান প্রতিস্থাপনput করবে এবং উপস্থিত না থাকলে এটি তৈরি করবে।


55
না, এটি তৈরি করে না, দেয় nullPointer Exception
smttsp

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

8
এই উত্তরটি ভুল। অ-বিদ্যমান কীগুলির জন্য নালপয়েন্টারএক্সেপশন
ইলানোর

@ এসএমটিপি নুলপয়েন্টার এক্সপ্রেশনটি কেবলমাত্র যদি আপনি মানটি আরম্ভ না করেন (যেমন আপনি জানেন যে আপনি নাল বৃদ্ধি করতে পারবেন না)
মেহেদী

সদৃশ এবং ভুল ব্যাখ্যা ... এবং বিদ্যমান না থাকলে এটি তৈরি করবে আপনি এটি করতে পারবেন না null + 1কারণ এটি বর্ধিতকরণের জন্য nullপূর্ণসংখ্যায় আনবক্স করার চেষ্টা করবে ।
এক্সেলএইচ

43

সরলীকৃত জাভা 8 উপায়:

map.put(key, map.getOrDefault(key, 0) + 1);

এটি হ্যাশম্যাপের পদ্ধতিটি ব্যবহার করে যা কোনও চাবির জন্য মানটি পুনরুদ্ধার করে, তবে কীটি পুনরুদ্ধার করা না গেলে এটি নির্দিষ্ট ডিফল্ট মান (এই ক্ষেত্রে '0') প্রদান করে।

এটি মূল জাভাতে সমর্থিত: হ্যাশম্যাপ <কে, ভি> getOrDefault (অবজেক্ট কী, ভি ডিফল্ট ভ্যালু)


3
আপনি জাভা ১.৮
হেমন্ত নাগপাল

30

Integerদ্বারা প্রতিস্থাপন করুন AtomicIntegerএবং এটিতে incrementAndGet/ getAndIncrementপদ্ধতিগুলির মধ্যে একটিতে কল করুন।

বিকল্পটি হ'ল intআপনার নিজস্ব MutableIntegerশ্রেণিতে increment()একটি মোড়ক রয়েছে যার একটি পদ্ধতি রয়েছে, সমাধান করার জন্য আপনার কাছে কেবল একটি থ্রেডসফটি উদ্বেগ রয়েছে।


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

কাস্টম ব্যবহার MutableIntegerহিসাবে ভাল, ওভারহেড যা ভাল । আমি এর পরিবর্তে ব্যবহার করব । AtomicIntegervolatileint[1]MutableInteger
অলিভ

@ অলিভ: একসাথে নয়
BalusC

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

@ অলিভ: প্রশ্নে স্পষ্টভাবে হ্যাশকোডের সংঘর্ষের কথা উল্লেখ করা হয়েছে, সুতরাং ওপি'র জন্য সম্মতি জরুরী।
BalusC

19

একটি লাইন সমাধান:

map.put(key, map.containsKey(key) ? map.get(key) + 1 : 1);

4
এটি বিদ্যমান উত্তরের সাথে নতুন কিছু যুক্ত করে না, তাই না?
রবার্ট

1
হ্যাঁ এটা করে. এটি সঠিক চিহ্নিত চিহ্নিত উত্তরটি যদি একটি উপস্থিত থাকে না তবে একটি নলপয়েন্টারএক্সেপশন নিক্ষেপ করবে। এই সমাধানটি ঠিক কাজ করবে।
হেমন্ত নাগপাল

18

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

আপনার যদি উচ্চ পারফরম্যান্সের প্রয়োজন হয় তবে অ্যাটমিকআইন্টিজার একটি ভাল সমাধান আলা @ বালুসসি।

যাইহোক, একটি দ্রুত সমাধান (প্রদত্ত থ্রেড সুরক্ষা কোনও সমস্যা নয়) TObjectIntHashMap ব্যবহার করা যা একটি ইনক্রিমেন্ট (কী) পদ্ধতি সরবরাহ করে এবং এটমিকআইন্টিজার তৈরির চেয়ে আদিম এবং কম বস্তু ব্যবহার করে। যেমন

TObjectIntHashMap<String> map = new TObjectIntHashMap<String>()
map.increment("aaa");

13

আপনি নীচের মতো বর্ধন করতে পারেন তবে আপনাকে অস্তিত্বের জন্য পরীক্ষা করতে হবে যাতে একটি নলপয়েন্টারেক্সেপশন নিক্ষেপ না হয়

if(!map.containsKey(key)) {
 p.put(key,1);
}
else {
 p.put(key, map.getKey()+1);
}

9

হ্যাশটি কি (মান হিসাবে 0 সহ) বিদ্যমান আছে বা এটি প্রথম বর্ধনে মানচিত্রে "লাগানো" আছে? যদি এটি প্রথম বর্ধিতকরণে "রাখা" হয়, কোডটি দেখতে এমন হওয়া উচিত:

if (hashmap.containsKey(key)) {
    hashmap.put(key, hashmap.get(key)+1);
} else { 
    hashmap.put(key,1);
}

7

কিছুটা দেরি হতে পারে তবে এখানে আমার দুটি সেন্ট রয়েছে।

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

final Map<String,Integer> map1 = new HashMap<>();
map1.put("A",0);
map1.put("B",0);
map1.computeIfPresent("B",(k,v)->v+1);  //[A=0, B=1]

কী লাগাতে আমরা আরেকটি পদ্ধতি putIfAbsent ব্যবহার করতে পারি । যদি নির্দিষ্ট কীটি ইতিমধ্যে কোনও মানের সাথে সম্পর্কিত না হয় (বা নালায় ম্যাপ করা থাকে) তবে এই পদ্ধতিটি প্রদত্ত মানের সাথে এটি যুক্ত করে এবং নালটি দেয়, অন্যথায় বর্তমান মানটি দেয়।

যদি মানচিত্রটি থ্রেডগুলিতে ভাগ করা হয় তবে আমরা ConcurrentHashMapএবং অ্যাটমিকআইন্টিজার ব্যবহার করতে পারি । ডক থেকে:

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

আমরা প্রদর্শিত হিসাবে সেগুলি ব্যবহার করতে পারি:

final Map<String,AtomicInteger> map2 = new ConcurrentHashMap<>();
map2.putIfAbsent("A",new AtomicInteger(0));
map2.putIfAbsent("B",new AtomicInteger(0)); //[A=0, B=0]
map2.get("B").incrementAndGet();    //[A=0, B=1]

একটি বিষয় লক্ষ্য করার জন্য আমরা getকীটির জন্য মানটি পেতে অনুরোধ করছি Bএবং এরপরে incrementAndGet()অবশ্যই এটির মানটি চাচ্ছি যা অবশ্যই AtomicInteger। পদ্ধতিটি putIfAbsentইতিমধ্যে উপস্থিত থাকলে কীটির মান ফেরত দেয় বলে আমরা এটি অনুকূল করতে পারি :

map2.putIfAbsent("B",new AtomicInteger(0)).incrementAndGet();//[A=0, B=2]

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



2

যেহেতু কম খ্যাতির কারণে আমি কয়েকটি উত্তরে মন্তব্য করতে পারি না, তাই আমি প্রয়োগ করা একটি সমাধান পোস্ট করব।

for(String key : someArray)
{
   if(hashMap.containsKey(key)//will check if a particular key exist or not 
   {
      hashMap.put(hashMap.get(key),value+1);// increment the value by 1 to an already existing key
   }
   else
   {
      hashMap.put(key,value);// make a new entry into the hashmap
   }
}

1

forসূচক বাড়ানোর জন্য একটি লুপ ব্যবহার করুন :

for (int i =0; i<5; i++){
    HashMap<String, Integer> map = new HashMap<String, Integer>();
    map.put("beer", 100);

    int beer = map.get("beer")+i;
    System.out.println("beer " + beer);
    System.out ....

}

3
এটি কেবল প্রতিটি পুনরাবৃত্তিতে মানচিত্রটি ওভাররাইট করে। সঠিক পদ্ধতির জন্য ম্যাথিউয়ের উত্তর দেখুন।
লেইচ

1

এখানে এই প্রশ্নের বিভ্রান্তিমূলক জবাব রয়েছে যে হ্যাশটেবল পুট পদ্ধতিটি যদি বিদ্যমান থাকে তবে বিদ্যমান মানটি প্রতিস্থাপন করবে, এটি হ্যাশটেবলের জন্য নয়, বরং হ্যাশম্যাপের জন্য সত্য। হ্যাশম্যাপের জন্য জাভাদোক দেখুন http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K ,% 20V%29


1
Integer i = map.get(key);
if(i == null)
   i = (aValue)
map.put(key, i + 1);

অথবা

Integer i = map.get(key);
map.put(key, i == null ? newValue : i + 1);

পূর্ণসংখ্যা হ'ল http://cs.fit.edu/~ryan/java/language/java-data.html তথ্যপ্রযুক্তি , তাই আপনাকে এটিকে বের করে আনতে হবে, কিছু প্রক্রিয়া করতে হবে এবং তারপরে এটি আবার রাখা উচিত। যদি আপনার এমন কোনও মান থাকে যা আদিম ডেটা ধরণের নয় তবে আপনার কেবল এটি বের করে নেওয়া দরকার, এটি প্রক্রিয়া করতে হবে, হ্যাশম্যাপে এটি আবার রাখার দরকার নেই।


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

0

চেষ্টা করুন:

HashMap hm=new HashMap<String ,Double >();

বিঃদ্রঃ:

String->give the new value; //THIS IS THE KEY
else
Double->pass new value; //THIS IS THE VALUE

আপনি আপনার হ্যাশম্যাপে কী বা মানটি পরিবর্তন করতে পারেন তবে আপনি একই সাথে দুটি পরিবর্তন করতে পারবেন না।


0

জালিয়াতি 'কম্পিউটিংআইফপ্রেসেন্ট' এ অন্তর্নির্মিত জাভা 8 ব্যবহার করুন

উদাহরণ:

public class ExampleToUpdateMapValue {

    public static void main(String[] args) {
        Map<String,String> bookAuthors = new TreeMap<>();
        bookAuthors.put("Genesis","Moses");
        bookAuthors.put("Joshua","Joshua");
        bookAuthors.put("Judges","Samuel");

        System.out.println("---------------------Before----------------------");
        bookAuthors.entrySet().stream().forEach(System.out::println);
        // To update the existing value using Java 8
        bookAuthors.computeIfPresent("Judges", (k,v) -> v = "Samuel/Nathan/Gad");

        System.out.println("---------------------After----------------------");
        bookAuthors.entrySet().stream().forEach(System.out::println);
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.