জাভা 8 তালিকা <ভি> মানচিত্রে <কে, ভি>


932

আমি জাভা 8 এর স্ট্রিম এবং ল্যাম্বডাস ব্যবহার করে একটি মানচিত্রে অবজেক্টের একটি তালিকা অনুবাদ করতে চাই।

এটি আমি জাভা 7 এবং নীচে এটি লিখব।

private Map<String, Choice> nameMap(List<Choice> choices) {
        final Map<String, Choice> hashMap = new HashMap<>();
        for (final Choice choice : choices) {
            hashMap.put(choice.getName(), choice);
        }
        return hashMap;
}

আমি জাভা 8 এবং পেয়ারা ব্যবহার করে এটি সহজেই সম্পাদন করতে পারি তবে আমি পেয়ারা ছাড়া এটি কীভাবে করব তা জানতে চাই।

পেয়ারাতে:

private Map<String, Choice> nameMap(List<Choice> choices) {
    return Maps.uniqueIndex(choices, new Function<Choice, String>() {

        @Override
        public String apply(final Choice input) {
            return input.getName();
        }
    });
}

এবং জাভা 8 লাম্বডাস সহ পেয়ারা।

private Map<String, Choice> nameMap(List<Choice> choices) {
    return Maps.uniqueIndex(choices, Choice::getName);
}

উত্তর:


1394

Collectorsডকুমেন্টেশনের ভিত্তিতে এটি এতটা সহজ:

Map<String, Choice> result =
    choices.stream().collect(Collectors.toMap(Choice::getName,
                                              Function.identity()));

167
পার্শ্ব নোট হিসাবে, জাভা 8 এর পরেও, জেডিকে এখনও ব্রেভিটি প্রতিযোগিতায় অংশ নিতে পারে না। পেয়ারা বিকল্প সৌন্দর্য এত পাঠযোগ্য: Maps.uniqueIndex(choices, Choice::getName)
বোগদান কলম্যাক

3
JOOL লাইব্রেরি Seqথেকে (স্থিতিশীলভাবে আমদানি করা) ব্যবহার করে ( যা আমি জাভা 8 ব্যবহার করে যে কাউকে সুপারিশ করব), seq(choices).toMap(Choice::getName)
আপনিও এই মাধ্যমে ব্রেভিটি

5
ফাংশন.ভিডেনসিটি ব্যবহার করে কি কোনও সুবিধা রয়েছে? মানে, এটি -> এটি সংক্ষিপ্ত
shabunc

9
@ শ্যাবুনক আমি কোনও উপকার সম্পর্কে জানি না এবং আসলে it -> itনিজেকে ব্যবহার করি। Function.identity()এখানে বেশিরভাগ ক্ষেত্রে ব্যবহৃত হয় কারণ এটি রেফারেন্সড ডকুমেন্টেশনে ব্যবহৃত হয় এবং লেখার সময়
ল্যাম্বডাস

12
উহু, @zapl, আসলে এটি সক্রিয় আউট সেখানে পিছনে এই কারণ আছে - stackoverflow.com/questions/28032827/...
shabunc

307

যদি আপনার কী তালিকার সমস্ত উপাদানগুলির জন্য অনন্য হওয়ার গ্যারান্টিযুক্ত না থাকে তবে আপনার এটির Map<String, List<Choice>>পরিবর্তে একটিতে রূপান্তর করা উচিতMap<String, Choice>

Map<String, List<Choice>> result =
 choices.stream().collect(Collectors.groupingBy(Choice::getName));

76
এটি আসলে আপনাকে মানচিত্র <স্ট্রিং, তালিকা <চয়েস>> দেয় যা অ-অনন্য কীগুলির সম্ভাবনা নিয়ে কাজ করে তবে ওপি অনুরোধ করে নি। পেয়ারাতে, মাল্টিম্যাপস.ইনডেক্স (পছন্দগুলি, পছন্দ: getName) সম্ভবত এটির চেয়ে ভাল বিকল্প যদি আপনি যেভাবে চান want
রিচার্ড নিকোলস

অথবা বরং পেয়ারার মাল্টিম্যাপ <স্ট্রিং, চয়েস> ব্যবহার করুন যা একাধিক মানের জন্য একই কী মানচিত্রের দৃশ্যে বেশ কার্যকর। মানচিত্র <স্ট্রিং, তালিকা <চয়েস>> তৈরি না করে এই জাতীয় ডেটা স্ট্রাকচারগুলি ব্যবহার করার জন্য পেয়ারাতে সহজেই বিভিন্ন ইউটিলিটি পদ্ধতি রয়েছে
নীরজ বি।

1
@ রিচার্ডনিচলস কেন পেয়ারা Multimapsপদ্ধতি আরও ভাল বিকল্প? এটি কোনও অসুবিধা হতে পারে যেহেতু এটি কোনও Mapবস্তু ফেরত দেয় না ।
theyuv

156

getName()কী Choiceহিসাবে এবং মানচিত্রের মান হিসাবে নিজেকে ব্যবহার করুন :

Map<String, Choice> result =
    choices.stream().collect(Collectors.toMap(Choice::getName, c -> c));

19
দয়া করে কিছু বর্ণনা লিখুন যাতে ব্যবহারকারী বুঝতে পারে।
মায়াঙ্ক জৈন

4
এটি খুব খারাপ যে এখানে আরও বিশদ নেই, কারণ আমি এই উত্তরটি সবচেয়ে পছন্দ করি।
ম্যাডকনান

Collectors.toMap(Choice::getName,c->c)(২ টি চর সংক্ষিপ্ত)
ফেরিবিগ

7
এটি choices.stream().collect(Collectors.toMap(choice -> choice.getName(),choice -> choice)); কী এর জন্য প্রথম ফাংশনের সমান ,
মূল্যটির

16
আমি জানি এবং দেখতে বুঝতে এটি কতটা সহজ c -> cতবে Function.identity()আরও শব্দাবলীর তথ্য বহন করে। আমি সাধারণত একটি স্থিতিশীল আমদানি ব্যবহার করি যাতে আমি কেবল ব্যবহার করতে পারিidentity()
হ্যাঙ্ক ডি

28

আপনি সংগ্রাহক.টোম্যাপ () ব্যবহার করতে না চান এমন ক্ষেত্রে এখানে আরও একটি রয়েছে

Map<String, Choice> result =
   choices.stream().collect(HashMap<String, Choice>::new, 
                           (m, c) -> m.put(c.getName(), c),
                           (m, u) -> {});

1
Collectors.toMap()উপরের উদাহরণে আপনি যেমনটি দেখিয়েছিলেন তা হলে আমাদের বা নিজের হ্যাশম্যাপটি ব্যবহার করা ভাল ?
স্বপ্নিল গ্যাংরেড

1
মানচিত্রে কীভাবে অন্য কিছু স্থাপন করা যায় তার উদাহরণ এই উদাহরণ সরবরাহ করে। আমি একটি পদ্ধতি কল দ্বারা প্রদত্ত একটি মান চেয়েছিলাম। ধন্যবাদ!
th3morg

1
তৃতীয় আর্গুমেন্ট ফাংশনটি সঠিক নয়। সেখানে আপনার দুটি হাশম্যাপ একীভূত করার জন্য কিছু ফাংশন সরবরাহ করা উচিত, যা হাশম্যাপ :: পুটআল
জেসন্তানা

25

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

public Map<String, Choice> convertListToMap(List<Choice> choices) {
    return choices.stream()
        .collect(Collectors.toMap(Choice::getName, choice -> choice,
            (oldValue, newValue) -> newValue));
  }

19

সহজ উপায়ে আরও একটি বিকল্প

Map<String,Choice> map = new HashMap<>();
choices.forEach(e->map.put(e.getName(),e));

3
এই বা জাভা 7 প্রকারটি ব্যবহারের ক্ষেত্রে কোনও কার্যকর পার্থক্য নেই।
আশীষ লোহিয়া

3
অন্যান্য প্রক্রিয়াগুলির তুলনায় কী চলছে তা পড়তে এবং বুঝতে আমি আরও সহজ পেয়েছি
ফ্রেইহাইট

2
এসও জাভা 8 স্ট্রিম সহ জিজ্ঞাসা করেছিল।
মেহরাজ মালিক

18

উদাহরণস্বরূপ, যদি আপনি অবজেক্ট ক্ষেত্রগুলিকে মানচিত্রে রূপান্তর করতে চান:

উদাহরণ বস্তু:

class Item{
        private String code;
        private String name;

        public Item(String code, String name) {
            this.code = code;
            this.name = name;
        }

        //getters and setters
    }

এবং অপারেশন তালিকা মানচিত্রে রূপান্তর:

List<Item> list = new ArrayList<>();
list.add(new Item("code1", "name1"));
list.add(new Item("code2", "name2"));

Map<String,String> map = list.stream()
     .collect(Collectors.toMap(Item::getCode, Item::getName));

12

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

ListX<Choices> choices;
Map<String, Choice> map = choices.toMap(c-> c.getName(),c->c);

10

আমি এটি করার চেষ্টা করে দেখেছি যে উপরের উত্তরগুলি ব্যবহার করে, Functions.identity()মানচিত্রের কীটি ব্যবহার করার সময়, তখন this::localMethodNameটাইপিংয়ের কারণে স্থানীয় পদ্ধতি ব্যবহার করার মতো আমার কাছে সমস্যা ছিল ।

Functions.identity()প্রকৃতপক্ষে এই ক্ষেত্রে টাইপিংয়ের জন্য কিছু করে তাই পদ্ধতিটি কেবল ফিরে আসে Objectএবং কোনও প্যারাম গ্রহণ করে তা কাজ করেObject

এটি সমাধান করার জন্য, আমি পরিবর্তে ডিচিং Functions.identity()এবং ব্যবহার শেষ করেছি s->s

সুতরাং আমার কোড, আমার ক্ষেত্রে একটি ডিরেক্টরিতে সমস্ত ডিরেক্টরি তালিকাভুক্ত করার জন্য, এবং প্রত্যেকের জন্য মানচিত্রের কী হিসাবে ডিরেক্টরিটির নাম ব্যবহার করুন এবং তারপরে ডিরেক্টরিটির নামের সাথে একটি পদ্ধতি কল করুন এবং আইটেমের সংকলনটি ফিরিয়ে দিন:

Map<String, Collection<ItemType>> items = Arrays.stream(itemFilesDir.listFiles(File::isDirectory))
.map(File::getName)
.collect(Collectors.toMap(s->s, this::retrieveBrandItems));

10

আপনি ইনটস্ট্রিম ব্যবহার করে সূচকের একটি স্ট্রিম তৈরি করতে পারেন এবং তারপরে এগুলিকে মানচিত্রে রূপান্তর করতে পারেন:

Map<Integer,Item> map = 
IntStream.range(0,items.size())
         .boxed()
         .collect(Collectors.toMap (i -> i, i -> items.get(i)));

1
এটি কোনও ভাল বিকল্প নয় কারণ আপনি প্রতিটি উপাদানের জন্য একটি () কল করেন, সুতরাং আইটেমগুলির হ্যাশম্যাপ হলে অপারেশনটির জটিলতা বাড়িয়ে তোলে (ও (এন * কে))।
নিকোলাস নোবেলিস

(I) হ্যাশম্যাপ হে (1) এ পাবেন না?
আইভো ভ্যান ডের ভীকেন

@ আইভোভান্ডারভিকেন উইন (আই) কোড স্নিপেট মানচিত্রে নয়, তালিকাতে রয়েছে।
জাকি

@ জাকি আমি নিকোলাসের মন্তব্য সম্পর্কে বলছিলাম। আইটেমগুলি তালিকার পরিবর্তে হ্যাশম্যাপ হলে আমি এন * কে জটিলতা দেখছি না।
আইভো ভ্যান ডের ভেকেন

8

জেনেরিকস এবং নিয়ন্ত্রণের বিপরীত ব্যবহার করে কীভাবে তালিকাটিকে মানচিত্রে রূপান্তর করতে হবে তা আমি লিখব । শুধু সর্বজনীন পদ্ধতি!

হতে পারে আমাদের কাছে পূর্ণসংখ্যার তালিকা বা বস্তুর তালিকা রয়েছে সুতরাং প্রশ্নটি নিম্নলিখিত: মানচিত্রের কী হওয়া উচিত ?

ইন্টারফেস তৈরি করুন

public interface KeyFinder<K, E> {
    K getKey(E e);
}

এখন নিয়ন্ত্রণের বিপরীতমুখী ব্যবহার:

  static <K, E> Map<K, E> listToMap(List<E> list, KeyFinder<K, E> finder) {
        return  list.stream().collect(Collectors.toMap(e -> finder.getKey(e) , e -> e));
    }

উদাহরণস্বরূপ, যদি আমাদের কাছে বইয়ের জিনিস থাকে তবে এই শ্রেণীর মানচিত্রের জন্য কী নির্বাচন করা উচিত

public class BookKeyFinder implements KeyFinder<Long, Book> {
    @Override
    public Long getKey(Book e) {
        return e.getPrice()
    }
}

6

আমি এই সিনট্যাক্সটি ব্যবহার করি

Map<Integer, List<Choice>> choiceMap = 
choices.stream().collect(Collectors.groupingBy(choice -> choice.getName()));

11
groupingByএকটি Map<K,List<V>>না, সৃষ্টি করে Map<K,V>
ক্রিস্টোফার হামারস্ট্রিম

3
উত্তর ডুপ। এবং, String getName();(পূর্ণসংখ্যার নয়)
বেরেট


4

এটি 2 উপায়ে করা যেতে পারে। ব্যক্তিটিকে আমরা এটি প্রদর্শনের জন্য যে শ্রেণিটি ব্যবহার করতে চাইছি তা হতে দিন।

public class Person {

    private String name;
    private int age;

    public String getAge() {
        return age;
    }
}

ব্যক্তিদের মানচিত্রে রূপান্তরিত করতে ব্যক্তির তালিকা হতে দিন

1. তালিকায় সরল ভবিষ্যদ্বাণী এবং একটি ল্যাম্বডা এক্সপ্রেশন ব্যবহার করে

Map<Integer,List<Person>> mapPersons = new HashMap<>();
persons.forEach(p->mapPersons.put(p.getAge(),p));

2. প্রদত্ত তালিকায় সংজ্ঞায়িত স্ট্রিমের সংগ্রাহক ব্যবহার করুন।

 Map<Integer,List<Person>> mapPersons = 
           persons.stream().collect(Collectors.groupingBy(Person::getAge));

4

এটি করার জন্য স্ট্রিম ব্যবহার করা সম্ভব। সুস্পষ্টভাবে ব্যবহারের প্রয়োজনীয়তা অপসারণ করার জন্য Collectors, toMapস্ট্যাটিকালি আমদানি করা সম্ভব (কার্যকর জাভা, তৃতীয় সংস্করণ দ্বারা প্রস্তাবিত)।

import static java.util.stream.Collectors.toMap;

private static Map<String, Choice> nameMap(List<Choice> choices) {
    return choices.stream().collect(toMap(Choice::getName, it -> it));
}


3
Map<String,Choice> map=list.stream().collect(Collectors.toMap(Choice::getName, s->s));

এমনকি আমার জন্য এই উদ্দেশ্যে কাজ করে,

Map<String,Choice> map=  list1.stream().collect(()-> new HashMap<String,Choice>(), 
            (r,s) -> r.put(s.getString(),s),(r,s) -> r.putAll(s));

3

যদি একই কী নামের প্রতিটি নতুন মানকে ওভাররাইড করতে হয়:

public Map < String, Choice > convertListToMap(List < Choice > choices) {
    return choices.stream()
        .collect(Collectors.toMap(Choice::getName,
            Function.identity(),
            (oldValue, newValue) - > newValue));
}

যদি সমস্ত পছন্দকে একটি নামের জন্য একটি তালিকায় গোষ্ঠীভুক্ত করতে হয়:

public Map < String, Choice > convertListToMap(List < Choice > choices) {
    return choices.stream().collect(Collectors.groupingBy(Choice::getName));
}

1
List<V> choices; // your list
Map<K,V> result = choices.stream().collect(Collectors.toMap(choice::getKey(),choice));
//assuming class "V" has a method to get the key, this method must handle case of duplicates too and provide a unique key.


-1
String array[] = {"ASDFASDFASDF","AA", "BBB", "CCCC", "DD", "EEDDDAD"};
    List<String> list = Arrays.asList(array);
    Map<Integer, String> map = list.stream()
            .collect(Collectors.toMap(s -> s.length(), s -> s, (x, y) -> {
                System.out.println("Dublicate key" + x);
                return x;
            },()-> new TreeMap<>((s1,s2)->s2.compareTo(s1))));
    System.out.println(map);

প্রজাতন্ত্র কী এএ {12 = এএসডিএফএএসডিএফএসডিএফ, 7 = ইইডিডিডিএড, 4 = সিসিসিসি, 3 = বিবিবি, 2 = এএ}


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