জাভা 8-এ আমি কোনও ল্যাম্বডা ব্যবহার করে একটি মানচিত্র <কে, ভি> কে অন্য মানচিত্র <কে, ভি> তে কীভাবে রূপান্তর করব?


140

আমি মাত্র জাভা 8 দেখতে শুরু করেছি এবং ল্যাম্বডাস চেষ্টা করার জন্য আমি ভেবেছিলাম যে আমি সম্প্রতি লিখেছি এমন একটি খুব সাধারণ জিনিস আবার লিখতে চেষ্টা করব re আমাকে স্ট্রিংয়ের একটি মানচিত্রকে কলামে স্ট্রিংয়ের অন্য মানচিত্রে কলামে পরিবর্তন করতে হবে যেখানে নতুন মানচিত্রে কলামটি প্রথম মানচিত্রে কলামের একটি প্রতিরক্ষামূলক অনুলিপি রয়েছে। কলামে একটি অনুলিপি নির্মাণকারী রয়েছে। আমি এখন পর্যন্ত সবচেয়ে কাছেরটি পেয়েছি:

    Map<String, Column> newColumnMap= new HashMap<>();
    originalColumnMap.entrySet().stream().forEach(x -> newColumnMap.put(x.getKey(), new Column(x.getValue())));

তবে আমি নিশ্চিত যে এটি করার একটি দুর্দান্ত উপায় অবশ্যই আছে এবং আমি কিছু পরামর্শের জন্য কৃতজ্ঞ হব।

উত্তর:


222

আপনি একজন সংগ্রাহক ব্যবহার করতে পারেন :

import java.util.*;
import java.util.stream.Collectors;

public class Defensive {

  public static void main(String[] args) {
    Map<String, Column> original = new HashMap<>();
    original.put("foo", new Column());
    original.put("bar", new Column());

    Map<String, Column> copy = original.entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getKey,
                                  e -> new Column(e.getValue())));

    System.out.println(original);
    System.out.println(copy);
  }

  static class Column {
    public Column() {}
    public Column(Column c) {}
  }
}

6
আমি মনে করি উপরের দিকে লক্ষ করার জন্য গুরুত্বপূর্ণ (এবং সামান্য পাল্টা স্বজ্ঞাত) জিনিসটি হ'ল রূপান্তরটি কোনও মানচিত্রের () স্ট্রিম অপারেশনের পরিবর্তে কালেক্টরে স্থান নেয়
ব্রায়ান অগ্নিউ

24
Map<String, Integer> map = new HashMap<>();
map.put("test1", 1);
map.put("test2", 2);

Map<String, Integer> map2 = new HashMap<>();
map.forEach(map2::put);

System.out.println("map: " + map);
System.out.println("map2: " + map2);
// Output:
// map:  {test2=2, test1=1}
// map2: {test2=2, test1=1}

আপনি forEachযা চান তা করতে আপনি পদ্ধতিটি ব্যবহার করতে পারেন।

আপনি সেখানে যা করছেন তা হ'ল:

map.forEach(new BiConsumer<String, Integer>() {
    @Override
    public void accept(String s, Integer integer) {
        map2.put(s, integer);     
    }
});

যা আমরা ল্যাম্বডায় সরল করতে পারি:

map.forEach((s, integer) ->  map2.put(s, integer));

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

map.forEach(map2::put);

8
আমি পছন্দ করি আপনি কীভাবে এখানে দৃশ্যের পিছনে কী চলছে তা ব্যাখ্যা করেছেন, এটি এটি আরও পরিষ্কার করে তোলে। তবে আমি মনে করি যে আমাকে কেবল আমার মূল মানচিত্রের একটি সরল অনুলিপি দেয়, একটি নতুন মানচিত্র নয় যেখানে মানগুলি প্রতিরক্ষা প্রতিলিপিগুলিতে রূপান্তরিত হয়েছে। আমি কি আপনাকে সঠিকভাবে বুঝতে পারি যে যে কারণে আমরা কেবল (map2 :: put) ব্যবহার করতে পারি তা হ'ল একই যুক্তিগুলি ল্যাম্বডায় intoুকছে, যেমন (গুলি, পূর্ণসংখ্যা) যেমন পুট পদ্ধতিতে যাচ্ছে? সুতরাং একটি প্রতিরক্ষামূলক অনুলিপি করতে কি এটি করা দরকার originalColumnMap.forEach((string, column) -> newColumnMap.put(string, new Column(column)));বা আমি এটি ছোট করতে পারি?
এনেসড্লেয়ার

হ্যা, তুমি. আপনি যদি কেবল একই যুক্তি দিয়ে যাচ্ছেন তবে আপনি কোনও পদ্ধতি রেফারেন্স ব্যবহার করতে পারেন, তবে এই ক্ষেত্রে, যেহেতু আপনার কাছে new Column(column)প্যারামিটার হিসাবে রয়েছে, আপনাকে অবশ্যই এটির সাথে যেতে হবে।
আরিরাম

আমি এই উত্তরটি আরও ভাল পছন্দ করি কারণ এটি যদি উভয় মানচিত্র ইতিমধ্যে আপনার কাছে সরবরাহ করা থাকে যেমন সেশন পুনর্নবীকরণের ক্ষেত্রে কার্যকর হয় works
ডেভিড স্ট্যানলি

এ জাতীয় উত্তরের বিষয়টি বুঝতে নিশ্চয়তা নেই। এটি একটি বিদ্যমান মানচিত্র থেকে বেশিরভাগই সমস্ত মানচিত্র বাস্তবায়নের প্রস্ততকর্তার rewriting হয় - মত এই
কিয়নোলিয়ান

13

নতুন মানচিত্রে সমস্ত এন্ট্রি পুনরায় সন্নিবিষ্ট না করার উপায়টি এটি দ্রুততম হওয়া উচিত কারণ HashMap.cloneঅভ্যন্তরীণভাবেও পুনঃস্থাপন করা হয়

Map<String, Column> newColumnMap = originalColumnMap.clone();
newColumnMap.replaceAll((s, c) -> new Column(c));

এটি করার একটি খুব পঠনযোগ্য উপায় এবং যথেষ্ট সংক্ষিপ্ত। দেখে মনে হচ্ছে হ্যাশম্যাপ.ক্লোন () আছে Map<String,Column> newColumnMap = new HashMap<>(originalColumnMap);। আমি জানি না এটি কভারগুলির নিচে কোনও আলাদা কিনা।
এনেসড্লেয়ার

2
এই পদ্ধতির Mapবাস্তবায়নের আচরণ রাখার সুবিধা রয়েছে , অর্থাত্ যদি Mapএটি একটি EnumMapবা একটি হয় SortedMapতবে ফলাফলটিও Mapততই হবে। SortedMapবিশেষের সাথে Comparatorএটির ক্ষেত্রে এটি একটি বিশাল অর্থগত পার্থক্য তৈরি করতে পারে। ওহ ভাল, IdentityHashMap
হোলার

8

এটি সরল রাখুন এবং জাভা 8 ব্যবহার করুন: -

 Map<String, AccountGroupMappingModel> mapAccountGroup=CustomerDAO.getAccountGroupMapping();
 Map<String, AccountGroupMappingModel> mapH2ToBydAccountGroups = 
              mapAccountGroup.entrySet().stream()
                         .collect(Collectors.toMap(e->e.getValue().getH2AccountGroup(),
                                                   e ->e.getValue())
                                  );

এই ক্ষেত্রে: map.forEach (map2 :: put); হয় সহজ :)
এসইএস

5

আপনি যদি আপনার প্রকল্পে পেয়ারা (v11 সর্বনিম্ন) ব্যবহার করেন তবে আপনি মানচিত্র :: ট্রান্সফর্মভ্যালু ব্যবহার করতে পারেন ।

Map<String, Column> newColumnMap = Maps.transformValues(
  originalColumnMap,
  Column::new // equivalent to: x -> new Column(x) 
)

দ্রষ্টব্য: এই মানচিত্রের মানগুলি অলসভাবে মূল্যায়ন করা হয়। যদি রূপান্তর ব্যয়বহুল হয় তবে আপনি ফলাফলটি পেয়ারা ডক্সে প্রস্তাবিত নতুন মানচিত্রে অনুলিপি করতে পারবেন।

To avoid lazy evaluation when the returned map doesn't need to be a view, copy the returned map into a new map of your choosing.

দ্রষ্টব্য: দস্তাবেজগুলির মতে, এটি মূল কলামম্যাপে অলস মূল্যায়িত মতামতটি ফিরিয়ে দেয়, সুতরাং কলামটি ফাংশন: প্রবেশের সময় প্রতিটি সময় প্রবেশের সময় পুনরায় মূল্যায়ন করা হয় (যা ম্যাপিং ফাংশন ব্যয়বহুল হলে কাঙ্ক্ষিত হতে পারে না)
এরিক

সঠিক। যদি রূপান্তর ব্যয়বহুল হয় তবে আপনি সম্ভবত নথিতে প্রস্তাবিত মতন একটি নতুন মানচিত্রে অনুলিপি করার ওভারহেড দিয়ে ভাল। To avoid lazy evaluation when the returned map doesn't need to be a view, copy the returned map into a new map of your choosing.
আন্দ্রেয়া বার্গনজো

সত্য, তবে যারা ডক্সটি পড়া বাদ দেন তাদের উত্তরে একটি পাদটীকা হিসাবে যুক্ত হওয়া উপযুক্ত।
এরিক

@ এরিক অর্থে তৈরি হয়েছে, স্রেফ যুক্ত হয়েছে।
Andrea Bergonzo

3

এখানে অন্য উপায় যা আপনাকে একই সাথে কী এবং মানটিতে অ্যাক্সেস দেয়, যদি আপনাকে কোনও ধরণের রূপান্তর করতে হয়।

Map<String, Integer> pointsByName = new HashMap<>();
Map<String, Integer> maxPointsByName = new HashMap<>();

Map<String, Double> gradesByName = pointsByName.entrySet().stream()
        .map(entry -> new AbstractMap.SimpleImmutableEntry<>(
                entry.getKey(), ((double) entry.getValue() /
                        maxPointsByName.get(entry.getKey())) * 100d))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

1

যদি আপনি তৃতীয় পক্ষের গ্রন্থাগারগুলি ব্যবহার করতে আপত্তি করেন না তবে আমার সাইক্লোপস-রিঅ্যাক্ট লাইবটিতে মানচিত্র সহ সমস্ত জেডিকে সংগ্রহের ধরণের জন্য এক্সটেনশন রয়েছে । আপনি আপনার মানচিত্রকে রূপান্তর করতে সরাসরি মানচিত্র বা বিম্যাপ পদ্ধতি ব্যবহার করতে পারেন। একটি মানচিত্র যেমন একটি বিদ্যমান মানচিত্র থেকে তৈরি করা যেতে পারে যেমন।

  MapX<String, Column> y = MapX.fromMap(orgColumnMap)
                               .map(c->new Column(c.getValue());

আপনি যদি চাবি পরিবর্তন করতে চান তবে আপনি লিখতে পারেন

  MapX<String, Column> y = MapX.fromMap(orgColumnMap)
                               .bimap(this::newKey,c->new Column(c.getValue());

বিম্যাপটি একই সাথে কী এবং মানগুলিকে রূপান্তর করতে ব্যবহার করা যেতে পারে।

ম্যাপএক্স ম্যাপটি প্রসারিত করার সাথে সাথে উত্পন্ন মানচিত্রটিকেও সংজ্ঞায়িত করা যায়

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