হাশম্যাপের জন্য নির্মাতা


109

পেয়ারা আমাদের জাভা প্রকারের জন্য দুর্দান্ত কারখানার পদ্ধতি সরবরাহ করে Maps.newHashMap()

তবে জাভা মানচিত্রের জন্য কি নির্মাতারা রয়েছেন?

HashMap<String,Integer> m = Maps.BuildHashMap.
    put("a",1).
    put("b",2).
    build();

উত্তর:


20

যেহেতু জাভা 9 Mapইন্টারফেসে রয়েছে:

  • Map.of(k1,v1, k2,v2, ..)
  • Map.ofEntries(Map.entry(k1,v1), Map.entry(k2,v2), ..)

এই কারখানা পদ্ধতির সীমাবদ্ধতা হ'ল:

  • nullকী এবং / অথবা মান হিসাবে গুলি ধরে রাখতে পারে না (যদি আপনাকে নালগুলি সঞ্চয় করতে হয় তবে অন্য উত্তরগুলি একবার দেখুন)
  • অপরিবর্তনীয় মানচিত্র উত্পাদন

আমাদের যদি পরিবর্তনীয় মানচিত্রের প্রয়োজন হয় (যেমন হাশম্যাপ) আমরা এর অনুলিপি-নির্মাতা ব্যবহার করতে পারি এবং এটির মাধ্যমে তৈরি করা মানচিত্রের সামগ্রীটি অনুলিপি করতে দিতে পারিMap.of(..)

Map<Integer, String> map = new HashMap<>( Map.of(1,"a", 2,"b", 3,"c") );

2
নোট করুন যে জাভা 9 টি পদ্ধতি nullমানগুলিকে অনুমতি দেয় না যা ব্যবহারের ক্ষেত্রে নির্ভর করে সমস্যা হতে পারে।
প্রতি লন্ডবার্গ

@JoshM। আইএমও Map.of(k1,v1, k2,v2, ...)নিরাপদে ব্যবহার করা যেতে পারে যখন আমাদের অনেক মান নেই। বৃহত্তর মানগুলির জন্য Map.ofEntries(Map.entry(k1,v1), Map.entry(k2,v2), ...)আমাদের আরও পঠনযোগ্য কোড দেয় যা ত্রুটির প্রবণতা কম (যদি না আমি আপনাকে ভুল বুঝি)।
Pshemo

আপনি ঠিক বুঝতে পেরেছেন। প্রাক্তনটি আমার কাছে সত্যিই স্থূল; আমি এটি ব্যবহার করতে অস্বীকার!
জোশ এম

164

হ্যাশম্যাপসের জন্য এ জাতীয় কোনও জিনিস নেই তবে আপনি একজন নির্মাতার সাথে একটি ইমটুটেবল ম্যাপ তৈরি করতে পারেন:

final Map<String, Integer> m = ImmutableMap.<String, Integer>builder().
      put("a", 1).
      put("b", 2).
      build();

এবং যদি আপনার কোনও পরিবর্তনীয় মানচিত্রের প্রয়োজন হয় তবে আপনি কেবল এটি হ্যাশম্যাপ কনস্ট্রাক্টরকে খাওয়ান।

final Map<String, Integer> m = Maps.newHashMap(
    ImmutableMap.<String, Integer>builder().
        put("a", 1).
        put("b", 2).
        build());

43
ImmutableMapnullমান সমর্থন করে না । তাই সেখানে এই পদ্ধতির সীমাবদ্ধতা হল: আপনি আপনার সেট করতে পারে না মান HashMapথেকে null
প্রাণবন্ত

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

2
@ ভিটিলি এর সাথে তর্ক করতে পারে না
সান প্যাট্রিক ফ্লয়েড

2
new HashMapস্থির Maps.newHashMapপদ্ধতির পরিবর্তে জাভা কনস্ট্রাক্টর ব্যবহারে কোনও ভুল আছে কি ?
CorayThan

1
@ কোরাইথান - জোনিক সঠিক, এটি স্ট্যাটিক ধরণের অনুক্রমের উপর নির্ভর করে কেবল একটি শর্টকাট। stackoverflow.com/a/13153812
AndersDJohnson

46

একেবারে বিল্ডার নয়, তবে একটি ইনিশিয়ালাইজার ব্যবহার করছেন:

Map<String, String> map = new HashMap<String, String>() {{
    put("a", "1");
    put("b", "2");
}};

অপেক্ষা করুন। যে map instanceof HashMapমিথ্যা না? একটি দুর্দান্ত-ধারণা হিসাবে মনে হচ্ছে।
এলাজার লাইবোভিচ

3
@ এলাজার map.getClass()==HashMap.classমিথ্যা প্রত্যাবর্তন করবে। তবে এটি যাইহোক একটি নির্বোধ পরীক্ষা। HashMap.class.isInstance(map)পছন্দ করা উচিত, এবং এটি সত্য ফিরে আসবে।
শন প্যাট্রিক ফ্লয়েড

59
এই বলেছিল: আমি এখনও এই সমাধানটি মন্দ বলে মনে করি।
শন প্যাট্রিক ফ্লয়েড

11
এটি স্ট্যান্ট ইনিশিয়ালাইজার নয়, উদাহরণস্বরূপ initial এটি সুপারের কনস্ট্রাক্টরের পরে চালানো হয়, তবে বর্গের প্রতিটি কনস্ট্রাক্টরের জন্য কনস্ট্রাক্টরের দেহের আগে। জীবনচক্রটি খুব সুপরিচিত নয় এবং তাই আমি এই প্রতিবাদটি এড়িয়ে চলেছি।
জো কোডার

14
এটি একটি খুব খারাপ সমাধান এবং এড়ানো উচিত: stackoverflow.com/a/27521360/3253277
আলেক্সান্ডার DuBreuil

36

এটি গ্রহণ করা উত্তরের মতো, তবে আমার দৃষ্টিতে কিছুটা ক্লিনার:

ImmutableMap.of("key1", val1, "key2", val2, "key3", val3);

উপরোক্ত পদ্ধতির বেশ কয়েকটি প্রকরণ রয়েছে এবং এগুলি স্থির, অপরিবর্তনীয়, পরিবর্তনীয় মানচিত্র তৈরির জন্য দুর্দান্ত great


4
আমি একজন বিল্ডারকে চেয়েছিলাম। আপনি মুষ্টিমেয় উপাদানগুলির মধ্যে সীমাবদ্ধ।
এলাজার লাইবোভিচ

সুন্দর এবং পরিষ্কার, তবে এটি পার্লের => অপারেটরের জন্য আমাকে দীর্ঘায়িত করে ... যা একটি আশ্চর্যজনক অনুভূতি।
অ্যারন মেনপা

10

এখানে একটি খুব সহজ ...

public class FluentHashMap<K, V> extends java.util.HashMap<K, V> {
  public FluentHashMap<K, V> with(K key, V value) {
    put(key, value);
    return this;
  }

  public static <K, V> FluentHashMap<K, V> map(K key, V value) {
    return new FluentHashMap<K, V>().with(key, value);
  }
}

তারপর

import static FluentHashMap.map;

HashMap<String, Integer> m = map("a", 1).with("b", 2);

Https://gist.github.com/culmat/a3bcc646fa4401641ac6eb01f3719065 দেখুন


আমি আপনার পদ্ধতির সরলতা পছন্দ করি। বিশেষত যেহেতু এটি 2017 (প্রায় 2018 এখন!), এবং
জেডিকে

সত্যিই দুর্দান্ত লাগছে, ধন্যবাদ। @ মিলাদনাসেরি এটি উন্মাদ যে জেদিকে এর এপিআইতে এখনও এর মতো কিছু নেই, কি লজ্জাজনক লজ্জা।
অসম্ভব

9

একটি সাধারণ মানচিত্র নির্মাতা লিখতে তুচ্ছ:

public class Maps {

    public static <Q,W> MapWrapper<Q,W> map(Q q, W w) {
        return new MapWrapper<Q, W>(q, w);
    }

    public static final class MapWrapper<Q,W> {
        private final HashMap<Q,W> map;
        public MapWrapper(Q q, W w) {
            map = new HashMap<Q, W>();
            map.put(q, w);
        }
        public MapWrapper<Q,W> map(Q q, W w) {
            map.put(q, w);
            return this;
        }
        public Map<Q,W> getMap() {
            return map;
        }
    }

    public static void main(String[] args) {
        Map<String, Integer> map = Maps.map("one", 1).map("two", 2).map("three", 3).getMap();
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
}

6

তুমি ব্যবহার করতে পার:

HashMap<String,Integer> m = Maps.newHashMap(
    ImmutableMap.of("a",1,"b",2)
);

এটি উত্কৃষ্ট এবং পাঠযোগ্য নয়, তবে কাজটি করে।


1
Map<String, Integer> map = ImmutableMap.of("a", 1, "b", 2);, উত্তম?
lschin

নির্মাতা হিসাবে একই, তবে সীমিত পরিমাণে ডেটা সহ, যেহেতু এটি ওভারলোডগুলি দিয়ে প্রয়োগ করা হয়েছে। আপনার যদি মাত্র কয়েকটি উপাদান থাকে - আমার ধারণা এটি ভাল it's
এলাজার লেইবোভিচ

4

HashMapপরিবর্তনীয়; কোনও বিল্ডারের দরকার নেই।

Map<String, Integer> map = Maps.newHashMap();
map.put("a", 1);
map.put("b", 2);

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

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

1
এর, ImmutableMapস্পষ্টত সেখানে বলা উচিত ছিল ।
কলিনড

আমি তাই মনে করি না. আমি বরং সংজ্ঞার একই লাইনে অন্তর্নিবেশকে দেখতে পাব, তারপরে এগুলি একটি অ-স্থিতিশীল অন্তর্নিহিতকরণে টান দিয়েছি {{init();}}( কনস্ট্রাক্টারে নয়, যেহেতু অন্য নির্মাণকারীরা এটি ভুলে যেতে পারে)। এবং এটি দুর্দান্ত যে এটি ধরণের পারমাণবিক ক্রিয়া। মানচিত্রটি যদি অস্থির হয় তবে কোনও বিল্ডারের সাথে এটি অন্তর্নিহিত করা নিশ্চিত করুন এটি সর্বদা হয় nullবা চূড়ান্ত অবস্থায় থাকে, কখনও অর্ধেক ভরা হয় না।
এলাজার লাইবোভিচ

1

আপনি গ্রহগ্রহের সংগ্রহগুলিতে সাবলীল এপিআই ব্যবহার করতে পারেন :

Map<String, Integer> map = Maps.mutable.<String, Integer>empty()
        .withKeyValue("a", 1)
        .withKeyValue("b", 2);

Assert.assertEquals(Maps.mutable.with("a", 1, "b", 2), map);

এখানে একটি ব্লগ আরও বিশদ এবং উদাহরণ সহ ।

দ্রষ্টব্য: আমি গ্রহগ্রাহ সংগ্রহের প্রতিশ্রুতিবদ্ধ।


0

কিছুক্ষণ আগে আমারও একই রকম প্রয়োজন ছিল। এটি পেয়ারার সাথে কিছুই করার নয় তবে আপনি Mapসাবলীল নির্মাতা ব্যবহার করে পরিষ্কারভাবে নির্মাণ করতে সক্ষম হবার জন্য এই জাতীয় কিছু করতে পারেন ।

মানচিত্র প্রসারিত একটি বেস ক্লাস তৈরি করুন।

public class FluentHashMap<K, V> extends LinkedHashMap<K, V> {
    private static final long serialVersionUID = 4857340227048063855L;

    public FluentHashMap() {}

    public FluentHashMap<K, V> delete(Object key) {
        this.remove(key);
        return this;
    }
}

তারপরে আপনার প্রয়োজন অনুসারে এমন পদ্ধতিতে সাবলীল নির্মাতা তৈরি করুন:

public class ValueMap extends FluentHashMap<String, Object> {
    private static final long serialVersionUID = 1L;

    public ValueMap() {}

    public ValueMap withValue(String key, String val) {
        super.put(key, val);
        return this;
    }

... Add withXYZ to suit...

}

তারপরে আপনি এটিকে এভাবে প্রয়োগ করতে পারেন:

ValueMap map = new ValueMap()
      .withValue("key 1", "value 1")
      .withValue("key 2", "value 2")
      .withValue("key 3", "value 3")

0

এটি এমন কিছু যা আমি সবসময় চেয়েছিলাম, বিশেষত টেস্ট ফিক্সচার সেটআপ করার সময়। অবশেষে, আমি সিদ্ধান্ত নিয়েছি যে আমার নিজস্ব একটি সহজ সাবলীল নির্মাতারা যেকোন মানচিত্রের বাস্তবায়ন তৈরি করতে পারে - https://gist.github.com/samshu/b471f5a2925fa9d9b718795d8bbdfe42#file-mapbuilder-java

    /**
     * @param mapClass Any {@link Map} implementation type. e.g., HashMap.class
     */
    public static <K, V> MapBuilder<K, V> builder(@SuppressWarnings("rawtypes") Class<? extends Map> mapClass)
            throws InstantiationException,
            IllegalAccessException {
        return new MapBuilder<K, V>(mapClass);
    }

    public MapBuilder<K, V> put(K key, V value) {
        map.put(key, value);
        return this;
    }

    public Map<K, V> build() {
        return map;
    }

0

আমি এখানে একটি লিখেছি

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class MapBuilder<K, V> {

    private final Map<K, V> map;

    /**
     * Create a HashMap builder
     */
    public MapBuilder() {
        map = new HashMap<>();
    }

    /**
     * Create a HashMap builder
     * @param initialCapacity
     */
    public MapBuilder(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

    /**
     * Create a Map builder
     * @param mapFactory
     */
    public MapBuilder(Supplier<Map<K, V>> mapFactory) {
        map = mapFactory.get();
    }

    public MapBuilder<K, V> put(K key, V value) {
        map.put(key, value);
        return this;
    }

    public Map<K, V> build() {
        return map;
    }

    /**
     * Returns an unmodifiable Map. Strictly speaking, the Map is not immutable because any code with a reference to
     * the builder could mutate it.
     *
     * @return
     */
    public Map<K, V> buildUnmodifiable() {
        return Collections.unmodifiableMap(map);
    }
}

আপনি এটি এর মতো ব্যবহার করুন:

Map<String, Object> map = new MapBuilder<String, Object>(LinkedHashMap::new)
    .put("event_type", newEvent.getType())
    .put("app_package_name", newEvent.getPackageName())
    .put("activity", newEvent.getActivity())
    .build();

0

জাভা 8 ব্যবহার করে:

এটি জাভা -9 এর একটি পদ্ধতির Map.ofEntries(Map.entry(k1,v1), Map.entry(k2,v2), ...)

public class MapUtil {
    import static java.util.stream.Collectors.toMap;

    import java.util.AbstractMap.SimpleEntry;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.stream.Stream;

    private MapUtil() {}

    @SafeVarargs
    public static Map<String, Object> ofEntries(SimpleEntry<String, Object>... values) {
        return Stream.of(values).collect(toMap(Entry::getKey, Entry::getValue));
    }

    public static SimpleEntry<String, Object> entry(String key, Object value) {
        return new SimpleEntry<String, Object>(key, value);
    }
}

ব্যবহারবিধি:

import static your.package.name.MapUtil.*;

import java.util.Map;

Map<String, Object> map = ofEntries(
        entry("id", 1),
        entry("description", "xyz"),
        entry("value", 1.05),
        entry("enable", true)
    );


0

ইনসকোর-জাভা হ্যাশম্যাপ তৈরি করতে পারে।

Map<String, Object> value = U.objectBuilder()
        .add("firstName", "John")
        .add("lastName", "Smith")
        .add("age", 25)
        .add("address", U.arrayBuilder()
            .add(U.objectBuilder()
                .add("streetAddress", "21 2nd Street")
                .add("city", "New York")
                .add("state", "NY")
                .add("postalCode", "10021")))
        .add("phoneNumber", U.arrayBuilder()
            .add(U.objectBuilder()
                .add("type", "home")
                .add("number", "212 555-1234"))
            .add(U.objectBuilder()
                .add("type", "fax")
                .add("number", "646 555-4567")))
        .build();
    // {firstName=John, lastName=Smith, age=25, address=[{streetAddress=21 2nd Street,
    // city=New York, state=NY, postalCode=10021}], phoneNumber=[{type=home, number=212 555-1234},
    // {type=fax, number=646 555-4567}]}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.