Czy możemy zaimplementować HashMap z jednym kluczem i dwiema wartościami. Podobnie jak HashMap?
Proszę, pomóżcie mi również, mówiąc (jeśli nie ma innego sposobu), aby zaimplementować przechowywanie trzech wartości, z których jedna jest kluczem?
Czy możemy zaimplementować HashMap z jednym kluczem i dwiema wartościami. Podobnie jak HashMap?
Proszę, pomóżcie mi również, mówiąc (jeśli nie ma innego sposobu), aby zaimplementować przechowywanie trzech wartości, z których jedna jest kluczem?
Odpowiedzi:
Mógłbyś:
Map<KeyType, List<ValueType>>.Map<KeyType, WrapperType>.Map<KeyType, Tuple<Value1Type, Value2Type>>.1. Mapa z listą jako wartością
// create our map
Map<String, List<Person>> peopleByForename = new HashMap<>();
// populate it
List<Person> people = new ArrayList<>();
people.add(new Person("Bob Smith"));
people.add(new Person("Bob Jones"));
peopleByForename.put("Bob", people);
// read from it
List<Person> bobs = peopleByForename["Bob"];
Person bob1 = bobs[0];
Person bob2 = bobs[1];
Wadą tego podejścia jest to, że lista nie jest powiązana z dokładnie dwiema wartościami.
2. Korzystanie z klasy opakowania
// define our wrapper
class Wrapper {
public Wrapper(Person person1, Person person2) {
this.person1 = person1;
this.person2 = person2;
}
public Person getPerson1 { return this.person1; }
public Person getPerson2 { return this.person2; }
private Person person1;
private Person person2;
}
// create our map
Map<String, Wrapper> peopleByForename = new HashMap<>();
// populate it
Wrapper people = new Wrapper();
peopleByForename.put("Bob", new Wrapper(new Person("Bob Smith"),
new Person("Bob Jones"));
// read from it
Wrapper bobs = peopleByForename.get("Bob");
Person bob1 = bobs.getPerson1;
Person bob2 = bobs.getPerson2;
Wadą tego podejścia jest to, że musisz napisać dużo kodu płyty kotłowej dla wszystkich tych bardzo prostych klas kontenerów.
3. Używanie krotki
// you'll have to write or download a Tuple class in Java, (.NET ships with one)
// create our map
Map<String, Tuple2<Person, Person> peopleByForename = new HashMap<>();
// populate it
peopleByForename.put("Bob", new Tuple2(new Person("Bob Smith",
new Person("Bob Jones"));
// read from it
Tuple<Person, Person> bobs = peopleByForename["Bob"];
Person bob1 = bobs.Item1;
Person bob2 = bobs.Item2;
To moim zdaniem najlepsze rozwiązanie.
4. Wiele map
// create our maps
Map<String, Person> firstPersonByForename = new HashMap<>();
Map<String, Person> secondPersonByForename = new HashMap<>();
// populate them
firstPersonByForename.put("Bob", new Person("Bob Smith"));
secondPersonByForename.put("Bob", new Person("Bob Jones"));
// read from them
Person bob1 = firstPersonByForename["Bob"];
Person bob2 = secondPersonByForename["Bob"];
Wadą tego rozwiązania jest to, że nie jest oczywiste, że dwie mapy są ze sobą powiązane, błąd programowy może spowodować, że dwie mapy nie zsynchronizują się.
Map<KeyType, Tuple<Value1Type, Value2Type>>
Nie, nie tylko jako HashMap. Zasadniczo potrzebujesz HashMapklucza od zbioru wartości.
Jeśli chcesz korzystać z bibliotek zewnętrznych, Guava ma dokładnie tę koncepcję w Multimapimplementacjach takich jak ArrayListMultimapi HashMultimap.
ArrayListMultimapty ... lub po prostu używałbyś czegoś takiego HashMap<String, List<Integer>>. Zasadniczo musisz utworzyć pustą listę za każdym razem, gdy wartość jest dodawana po raz pierwszy.
HashMap<String, List<Integer>>
Innym dobrym wyborem jest użycie MultiValuedMap z Apache Commons. Spójrz na Wszystkie znane klasy implementacyjne u góry strony, aby uzyskać specjalistyczne implementacje.
Przykład:
HashMap<K, ArrayList<String>> map = new HashMap<K, ArrayList<String>>()
można zastąpić
MultiValuedMap<K, String> map = new MultiValuedHashMap<K, String>();
Więc,
map.put(key, "A");
map.put(key, "B");
map.put(key, "C");
Collection<String> coll = map.get(key);
spowoduje, że kolekcja będzie collzawierać „A”, „B” i „C”.
Spójrz na Multimapbiblioteki guava i jej implementację -HashMultimap
Kolekcja podobna do mapy, ale która może powiązać wiele wartości z jednym kluczem. Jeśli wywołasz put (K, V) dwa razy, z tym samym kluczem, ale różnymi wartościami, multimapa zawiera odwzorowania z klucza na obie wartości.
używam Map<KeyType, Object[]> do kojarzenia wielu wartości z kluczem na mapie. W ten sposób mogę przechowywać wiele wartości różnych typów powiązanych z kluczem. Musisz zachować ostrożność, zachowując odpowiednią kolejność wstawiania i pobierania z Object [].
Przykład: Rozważmy, że chcemy przechowywać informacje o studentach. Kluczem jest identyfikator, a my chcielibyśmy przechowywać imię i nazwisko, adres i adres e-mail powiązany z uczniem.
//To make entry into Map
Map<Integer, String[]> studenMap = new HashMap<Integer, String[]>();
String[] studentInformationArray = new String[]{"name", "address", "email"};
int studenId = 1;
studenMap.put(studenId, studentInformationArray);
//To retrieve values from Map
String name = studenMap.get(studenId)[1];
String address = studenMap.get(studenId)[2];
String email = studenMap.get(studenId)[3];
HashMap<Integer,ArrayList<String>> map = new HashMap<Integer,ArrayList<String>>();
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("xyz");
map.put(100,list);
Dla przypomnienia, czystym rozwiązaniem JDK8 byłoby użycie Map::computemetody:
map.compute(key, (s, strings) -> strings == null ? new ArrayList<>() : strings).add(value);
Jak na przykład
public static void main(String[] args) {
Map<String, List<String>> map = new HashMap<>();
put(map, "first", "hello");
put(map, "first", "foo");
put(map, "bar", "foo");
put(map, "first", "hello");
map.forEach((s, strings) -> {
System.out.print(s + ": ");
System.out.println(strings.stream().collect(Collectors.joining(", ")));
});
}
private static <KEY, VALUE> void put(Map<KEY, List<VALUE>> map, KEY key, VALUE value) {
map.compute(key, (s, strings) -> strings == null ? new ArrayList<>() : strings).add(value);
}
z wyjściem:
bar: foo
first: hello, foo, hello
Należy pamiętać, że w celu zapewnienia spójności w przypadku, gdy wiele wątków uzyskuje dostęp do tej struktury danych, ConcurrentHashMapi CopyOnWriteArrayListna przykład należy użyć.
computeIfAbsent. map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
Jeśli korzystasz z Spring Framework . Jest:org.springframework.util.MultiValueMap .
Aby utworzyć niemodyfikowalną mapę wielu wartości:
Map<String,List<String>> map = ...
MultiValueMap<String, String> multiValueMap = CollectionUtils.toMultiValueMap(map);
Albo użyj org.springframework.util.LinkedMultiValueMap
Tak, często nazywane jest to multimap .
Najprostszym sposobem byłoby użycie biblioteki kolekcji Google:
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
public class Test {
public static void main(final String[] args) {
// multimap can handle one key with a list of values
final Multimap<String, String> cars = ArrayListMultimap.create();
cars.put("Nissan", "Qashqai");
cars.put("Nissan", "Juke");
cars.put("Bmw", "M3");
cars.put("Bmw", "330E");
cars.put("Bmw", "X6");
cars.put("Bmw", "X5");
cars.get("Bmw").forEach(System.out::println);
// It will print the:
// M3
// 330E
// X6
// X5
}
}
link maven: https://mvnrepository.com/artifact/com.google.collections/google-collections/1.0-rc2
więcej na ten temat: http://tomjefferys.blogspot.be/2011/09/multimaps-google-guava.html
String key= "services_servicename"
ArrayList<String> data;
for(int i = 0; i lessthen data.size(); i++) {
HashMap<String, String> servicesNameHashmap = new HashMap<String, String>();
servicesNameHashmap.put(key,data.get(i).getServiceName());
mServiceNameArray.add(i,servicesNameHashmap);
}
Mam najlepsze wyniki.
Po prostu trzeba stworzyć nową HashMapodczuwalna
HashMap<String, String> servicesNameHashmap = new HashMap<String, String>();
w twojej forpętli. Będzie to miało taki sam efekt jak ten sam klucz i wiele wartości.
import java.io.*;
import java.util.*;
import com.google.common.collect.*;
class finTech{
public static void main(String args[]){
Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("1","11");
multimap.put("1","14");
multimap.put("1","12");
multimap.put("1","13");
multimap.put("11","111");
multimap.put("12","121");
System.out.println(multimap);
System.out.println(multimap.get("11"));
}
}
Wynik:
{"1"=["11","12","13","14"],"11"=["111"],"12"=["121"]}
["111"]
To jest biblioteka Google-Guava dla funkcji narzędziowych. To jest wymagane rozwiązanie.
Nie mogłem opublikować odpowiedzi na komentarz Paula, dlatego tworzę nowy komentarz do Vidhya tutaj:
Opakowanie będzie SuperClassdla dwóch klas, które chcemy przechowywać jako wartość.
a wewnątrz klasy opakowania możemy umieścić powiązania jako obiekty zmiennej instancji dla dwóch obiektów klasy.
na przykład
class MyWrapper {
Class1 class1obj = new Class1();
Class2 class2obj = new Class2();
...
}
a w HashMap możemy to w ten sposób umieścić,
Map<KeyObject, WrapperObject>
WrapperObj będzie miał zmienne klasowe:class1Obj, class2Obj
Możesz to zrobić niejawnie.
// Create the map. There is no restriction to the size that the array String can have
HashMap<Integer, String[]> map = new HashMap<Integer, String[]>();
//initialize a key chosing the array of String you want for your values
map.put(1, new String[] { "name1", "name2" });
//edit value of a key
map.get(1)[0] = "othername";
To jest bardzo proste i skuteczne. Jeśli zamiast tego chcesz wartości różnych klas, możesz wykonać następujące czynności:
HashMap<Integer, Object[]> map = new HashMap<Integer, Object[]>();
Można to zrobić za pomocą tożsamościHashMap, pod warunkiem, że porównanie kluczy zostanie wykonane przez operator ==, a nie równa się ().
Wolę następujące do przechowywania dowolnej liczby zmiennych bez konieczności tworzenia osobnej klasy.
final public static Map<String, Map<String, Float>> myMap = new HashMap<String, Map<String, Float>>();
Jestem tak przyzwyczajony do robienia tego za pomocą Słownika danych w Celu C. Trudniej było uzyskać podobny wynik w Javie dla Androida. W końcu stworzyłem niestandardową klasę, a następnie po prostu wykonałem mapę mojej niestandardowej klasy.
public class Test1 {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.addview);
//create the datastring
HashMap<Integer, myClass> hm = new HashMap<Integer, myClass>();
hm.put(1, new myClass("Car", "Small", 3000));
hm.put(2, new myClass("Truck", "Large", 4000));
hm.put(3, new myClass("Motorcycle", "Small", 1000));
//pull the datastring back for a specific item.
//also can edit the data using the set methods. this just shows getting it for display.
myClass test1 = hm.get(1);
String testitem = test1.getItem();
int testprice = test1.getPrice();
Log.i("Class Info Example",testitem+Integer.toString(testprice));
}
}
//custom class. You could make it public to use on several activities, or just include in the activity if using only here
class myClass{
private String item;
private String type;
private int price;
public myClass(String itm, String ty, int pr){
this.item = itm;
this.price = pr;
this.type = ty;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public String getType() {
return item;
}
public void setType(String type) {
this.type = type;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
Możemy stworzyć klasę posiadającą wiele kluczy lub wartości, a obiekt tej klasy może być użyty jako parametr w mapie. Możesz odnieść się do https://stackoverflow.com/a/44181931/8065321
Korzystanie z kolektorów Java
// Group employees by department
Map<Department, List<Employee>> byDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
gdzie Departament jest twoim kluczem
Wypróbuj LinkedHashMap , przykład:
Map<String,String> map = new LinkedHashMap<String,String>();
map.put('1','linked');map.put('1','hash');
map.put('2','map');map.put('3','java');..
wynik:
klucze: 1,1,2,3
wartości: połączone, skrót, mapa, java
linkednie będzie już istniał na mapie, ponieważ zastąpiłeś ją hash.