Why sublist is not working on List<Object>? - java

I am trying to get subList from List<Object> this way,
My actual map data before doing sublist is this way,
Converted Map{Demography=[[D11,D22,D99]], Paper=[[[EEE,RRR,TTT],[QQQ,WWW,EEE],[UUU,III,OOO]]], Hunt=[[HUT,HUG,HUE]], Camp=[[COL,CIL,CPL]]
and my code is this,
public class PosTest {
HashMap<String, Object> uiMap = new HashMap<String, Object>();
public static void main(String[] args) {
PosTest mm = new PosTest();
mm.getSupplierInfo();
}
public void getSupplierInfo()
{
HashMap<String, Object> jsonMap = new HashMap<String, Object>();
jsonMap.put("Camp","[COL,CIL,CPL]");
jsonMap.put("Demography","[D11,D22,D99]");
jsonMap.put("Hunt","[HUT,HUG,HUE]");
jsonMap.put("Paper","[[EEE,RRR,TTT],[QQQ,WWW,EEE],[UUU,III,OOO]]");
Iterator<Entry<String, Object>> i = jsonMap.entrySet().iterator();
Entry<String, Object> e = null;
List<Object> eValue = null;
while (i.hasNext()) {
e = i.next();
eValue = Arrays.asList(e.getValue());
uiMap.put(e.getKey(), eValue.subList(0, 1));
}
System.out.println("Converted Map" + uiMap);
}
}
Then when i call uiMap.put(e.getKey(), eValue.subList(0, 1)); i should get only 0,1 of values from list, i.e,
Converted Map{Demography=[D11,D22], Paper=[[EEE,RRR,TTT],[QQQ,WWW,EEE]], Hunt=[HUT,HUG]], Camp=[COL,CIL]}
But My output from that code is Converted Map{Demography=[[D11,D22,D99]], Paper=[[[EEE,RRR,TTT],[QQQ,WWW,EEE],[UUU,III,OOO]]], Hunt=[[HUT,HUG,HUE]], Camp=[[COL,CIL,CPL]]}
Why all the list values are returned without sublist (0,1) and also one extra brace is added?
Can anyone help me in this issue?

Are you assuming that Java can interpret "[COL,CIL,CPL]" as a list? It cannot. It’s one object of type String.
When you call Arrays.asList(), because of varargs, Java produces first an array of one String element, then asList() converts that into a list of one element. The subList(0, 1) of this list is the same list. This is why you get the same thing out as you put in.

By this:
jsonMap.put("Hunt","[HUT,HUG,HUE]");
you don't put a list as a value, you put the only string. And this:
eValue = Arrays.asList(e.getValue());
doesn't magically parse "[COL,CIL,CPL]" to a list, it just creates one-item list containing that single string, which subList(0, 1) returns itself (as it has only one item).
So, first change the type of jsonMap to Map<String, List<String>>, and put items by:
jsonMap.put("Hunt", Arrays.asList("HUT", "HUG", "HUE"));
jsonMap.put("Hunt", Arrays.asList("D11", "D22", "D99"));
//...
then, to get a sublist, call:
uiMap.put(key, jsonMap.get(key).subList(0, 1));

Related

What's the best Java data structure for multiple values with same key? [duplicate]

How I can get the third value for the first key in this map? Is this possible?
Libraries exist to do this, but the simplest plain Java way is to create a Map of List like this:
Map<Object,ArrayList<Object>> multiMap = new HashMap<>();
It sounds like you're looking for a multimap. Guava has various Multimap implementations, usually created via the Multimaps class.
I would suggest that using that implementation is likely to be simpler than rolling your own, working out what the API should look like, carefully checking for an existing list when adding a value etc. If your situation has a particular aversion to third party libraries it may be worth doing that, but otherwise Guava is a fabulous library which will probably help you with other code too :)
For example:
Map<Object,Pair<Integer,String>> multiMap = new HashMap<Object,Pair<Integer,String>>();
where the Pair is a parametric class
public class Pair<A, B> {
A first = null;
B second = null;
Pair(A first, B second) {
this.first = first;
this.second = second;
}
public A getFirst() {
return first;
}
public void setFirst(A first) {
this.first = first;
}
public B getSecond() {
return second;
}
public void setSecond(B second) {
this.second = second;
}
}
This is what i found in a similar question's answer
Map<String, List<String>> hm = new HashMap<String, List<String>>();
List<String> values = new ArrayList<String>();
values.add("Value 1");
values.add("Value 2");
hm.put("Key1", values);
// to get the arraylist
System.out.println(hm.get("key1"));
RESULT: [Value 1, Value 2]
A standard Java HashMap cannot store multiple values per key, any new entry you add will overwrite the previous one.
Have you got something like this?
HashMap<String, ArrayList<String>>
If so, you can iterate through your ArrayList and get the item you like with arrayList.get(i).
I found the blog on random search, i think this will help for doing this: http://tomjefferys.blogspot.com.tr/2011/09/multimaps-google-guava.html
public class MutliMapTest {
public static void main(String... args) {
Multimap<String, String> myMultimap = ArrayListMultimap.create();
// Adding some key/value
myMultimap.put("Fruits", "Bannana");
myMultimap.put("Fruits", "Apple");
myMultimap.put("Fruits", "Pear");
myMultimap.put("Vegetables", "Carrot");
// Getting the size
int size = myMultimap.size();
System.out.println(size); // 4
// Getting values
Collection<String> fruits = myMultimap.get("Fruits");
System.out.println(fruits); // [Bannana, Apple, Pear]
Collection<string> vegetables = myMultimap.get("Vegetables");
System.out.println(vegetables); // [Carrot]
// Iterating over entire Mutlimap
for(String value : myMultimap.values()) {
System.out.println(value);
}
// Removing a single value
myMultimap.remove("Fruits","Pear");
System.out.println(myMultimap.get("Fruits")); // [Bannana, Pear]
// Remove all values for a key
myMultimap.removeAll("Fruits");
System.out.println(myMultimap.get("Fruits")); // [] (Empty Collection!)
}
}
Try using collections to store the values of a key:
Map<Key, Collection<Value>>
you have to maintain the value list yourself
Apache Commons collection classes is the solution.
MultiMap multiMapDemo = new MultiValueMap();
multiMapDemo .put("fruit", "Mango");
multiMapDemo .put("fruit", "Orange");
multiMapDemo.put("fruit", "Blueberry");
System.out.println(multiMap.get("fruit"));
// Mango Orange Blueberry
Maven Dependency
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 --
>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
Apart from all the answers here, I have a solution that I used and found it most useful if you know the length of multiple values to be added to your key.
In my case, it was 2, so I opted for this over a List<string>.
HashMap<String, String[]> multimap= new HashMap<>();
multimap.put("my_key", new String[]{"my_value1", "my_value2"});
Thinking about a Map with 2 keys immediately compelled me to use a user-defined key, and that would probably be a Class. Following is the key Class:
public class MapKey {
private Object key1;
private Object key2;
public Object getKey1() {
return key1;
}
public void setKey1(Object key1) {
this.key1 = key1;
}
public Object getKey2() {
return key2;
}
public void setKey2(Object key2) {
this.key2 = key2;
}
}
// Create first map entry with key <A,B>.
MapKey mapKey1 = new MapKey();
mapKey1.setKey1("A");
mapKey1.setKey2("B");
HashMap – Single Key and Multiple Values Using List
Map<String, List<String>> map = new HashMap<String, List<String>>();
// create list one and store values
List<String> One = new ArrayList<String>();
One.add("Apple");
One.add("Aeroplane");
// create list two and store values
List<String> Two = new ArrayList<String>();
Two.add("Bat");
Two.add("Banana");
// put values into map
map.put("A", One);
map.put("B", Two);
map.put("C", Three);
You can do something like this (add access modifiers as required):
Map<String,Map<String,String>> complexMap=new HashMap<String,Map<String,String>>();
You can insert data like this:
Map<String,String> componentMap = new HashMap<String,String>();
componentMap.put("foo","bar");
componentMap.put("secondFoo","secondBar");
complexMap.put("superFoo",componentMap);
The Generated Data Structure would be:
{superFoo={secondFoo=secondBar, foo=bar}}
This way each value for the key should have a unique identifier. Also gives O(1) for fetches,if keys are known.
Write a new class that holds all the values that you need and use the new class's object as the value in your HashMap
HashMap<String, MyObject>
class MyObject {
public String value1;
public int value2;
public List<String> value3;
}
Here is the code how to get extract the hashmap into arrays, hashmap that contains arraylist
Map<String, List<String>> country_hashmap = new HashMap<String, List<String>>();
//Creating two lists and inserting some data in it
List<String> list_1 = new ArrayList<String>();
list_1.add("16873538.webp");
list_1.add("16873539.webp");
List<String> list_2 = new ArrayList<String>();
list_2.add("16873540.webp");
list_2.add("16873541.webp");
//Inserting both the lists and key to the Map
country_hashmap.put("Malaysia", list_1);
country_hashmap.put("Japanese", list_2);
for(Map.Entry<String, List<String>> hashmap_data : country_hashmap.entrySet()){
String key = hashmap_data.getKey(); // contains the keys
List<String> val = hashmap_data.getValue(); // contains arraylists
// print all the key and values in the hashmap
System.out.println(key + ": " +val);
// using interator to get the specific values arraylists
Iterator<String> itr = val.iterator();
int i = 0;
String[] data = new String[val.size()];
while (itr.hasNext()){
String array = itr.next();
data[i] = array;
System.out.println(data[i]); // GET THE VALUE
i++;
}
}

Which type of collections to use for storing a country list [duplicate]

How I can get the third value for the first key in this map? Is this possible?
Libraries exist to do this, but the simplest plain Java way is to create a Map of List like this:
Map<Object,ArrayList<Object>> multiMap = new HashMap<>();
It sounds like you're looking for a multimap. Guava has various Multimap implementations, usually created via the Multimaps class.
I would suggest that using that implementation is likely to be simpler than rolling your own, working out what the API should look like, carefully checking for an existing list when adding a value etc. If your situation has a particular aversion to third party libraries it may be worth doing that, but otherwise Guava is a fabulous library which will probably help you with other code too :)
For example:
Map<Object,Pair<Integer,String>> multiMap = new HashMap<Object,Pair<Integer,String>>();
where the Pair is a parametric class
public class Pair<A, B> {
A first = null;
B second = null;
Pair(A first, B second) {
this.first = first;
this.second = second;
}
public A getFirst() {
return first;
}
public void setFirst(A first) {
this.first = first;
}
public B getSecond() {
return second;
}
public void setSecond(B second) {
this.second = second;
}
}
This is what i found in a similar question's answer
Map<String, List<String>> hm = new HashMap<String, List<String>>();
List<String> values = new ArrayList<String>();
values.add("Value 1");
values.add("Value 2");
hm.put("Key1", values);
// to get the arraylist
System.out.println(hm.get("key1"));
RESULT: [Value 1, Value 2]
A standard Java HashMap cannot store multiple values per key, any new entry you add will overwrite the previous one.
Have you got something like this?
HashMap<String, ArrayList<String>>
If so, you can iterate through your ArrayList and get the item you like with arrayList.get(i).
I found the blog on random search, i think this will help for doing this: http://tomjefferys.blogspot.com.tr/2011/09/multimaps-google-guava.html
public class MutliMapTest {
public static void main(String... args) {
Multimap<String, String> myMultimap = ArrayListMultimap.create();
// Adding some key/value
myMultimap.put("Fruits", "Bannana");
myMultimap.put("Fruits", "Apple");
myMultimap.put("Fruits", "Pear");
myMultimap.put("Vegetables", "Carrot");
// Getting the size
int size = myMultimap.size();
System.out.println(size); // 4
// Getting values
Collection<String> fruits = myMultimap.get("Fruits");
System.out.println(fruits); // [Bannana, Apple, Pear]
Collection<string> vegetables = myMultimap.get("Vegetables");
System.out.println(vegetables); // [Carrot]
// Iterating over entire Mutlimap
for(String value : myMultimap.values()) {
System.out.println(value);
}
// Removing a single value
myMultimap.remove("Fruits","Pear");
System.out.println(myMultimap.get("Fruits")); // [Bannana, Pear]
// Remove all values for a key
myMultimap.removeAll("Fruits");
System.out.println(myMultimap.get("Fruits")); // [] (Empty Collection!)
}
}
Try using collections to store the values of a key:
Map<Key, Collection<Value>>
you have to maintain the value list yourself
Apache Commons collection classes is the solution.
MultiMap multiMapDemo = new MultiValueMap();
multiMapDemo .put("fruit", "Mango");
multiMapDemo .put("fruit", "Orange");
multiMapDemo.put("fruit", "Blueberry");
System.out.println(multiMap.get("fruit"));
// Mango Orange Blueberry
Maven Dependency
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 --
>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
Apart from all the answers here, I have a solution that I used and found it most useful if you know the length of multiple values to be added to your key.
In my case, it was 2, so I opted for this over a List<string>.
HashMap<String, String[]> multimap= new HashMap<>();
multimap.put("my_key", new String[]{"my_value1", "my_value2"});
Thinking about a Map with 2 keys immediately compelled me to use a user-defined key, and that would probably be a Class. Following is the key Class:
public class MapKey {
private Object key1;
private Object key2;
public Object getKey1() {
return key1;
}
public void setKey1(Object key1) {
this.key1 = key1;
}
public Object getKey2() {
return key2;
}
public void setKey2(Object key2) {
this.key2 = key2;
}
}
// Create first map entry with key <A,B>.
MapKey mapKey1 = new MapKey();
mapKey1.setKey1("A");
mapKey1.setKey2("B");
HashMap – Single Key and Multiple Values Using List
Map<String, List<String>> map = new HashMap<String, List<String>>();
// create list one and store values
List<String> One = new ArrayList<String>();
One.add("Apple");
One.add("Aeroplane");
// create list two and store values
List<String> Two = new ArrayList<String>();
Two.add("Bat");
Two.add("Banana");
// put values into map
map.put("A", One);
map.put("B", Two);
map.put("C", Three);
You can do something like this (add access modifiers as required):
Map<String,Map<String,String>> complexMap=new HashMap<String,Map<String,String>>();
You can insert data like this:
Map<String,String> componentMap = new HashMap<String,String>();
componentMap.put("foo","bar");
componentMap.put("secondFoo","secondBar");
complexMap.put("superFoo",componentMap);
The Generated Data Structure would be:
{superFoo={secondFoo=secondBar, foo=bar}}
This way each value for the key should have a unique identifier. Also gives O(1) for fetches,if keys are known.
Write a new class that holds all the values that you need and use the new class's object as the value in your HashMap
HashMap<String, MyObject>
class MyObject {
public String value1;
public int value2;
public List<String> value3;
}
Here is the code how to get extract the hashmap into arrays, hashmap that contains arraylist
Map<String, List<String>> country_hashmap = new HashMap<String, List<String>>();
//Creating two lists and inserting some data in it
List<String> list_1 = new ArrayList<String>();
list_1.add("16873538.webp");
list_1.add("16873539.webp");
List<String> list_2 = new ArrayList<String>();
list_2.add("16873540.webp");
list_2.add("16873541.webp");
//Inserting both the lists and key to the Map
country_hashmap.put("Malaysia", list_1);
country_hashmap.put("Japanese", list_2);
for(Map.Entry<String, List<String>> hashmap_data : country_hashmap.entrySet()){
String key = hashmap_data.getKey(); // contains the keys
List<String> val = hashmap_data.getValue(); // contains arraylists
// print all the key and values in the hashmap
System.out.println(key + ": " +val);
// using interator to get the specific values arraylists
Iterator<String> itr = val.iterator();
int i = 0;
String[] data = new String[val.size()];
while (itr.hasNext()){
String array = itr.next();
data[i] = array;
System.out.println(data[i]); // GET THE VALUE
i++;
}
}

How to add a value to a list of values for a single key in a hashmap (Java)

I have written this:
HashMap<String, String> map1 = new HashMap<String, String>();
Map<String, ArrayList<String>> map2 = new HashMap<String, ArrayList<String>>();
i am trying to allow more then 1 value for each key in a hashmap. so if the first key is '1', i want to allow '1' to be paired with values '2' and '3'.
so it be like:
1 --> 2
|--> 3
but when I do:
map2.put(key, value);
it gives error that says "incompatible types" and it can not be converted to ArrayList and it says the error is at the value part of the line.
If you are using Java 8, you can do this quite easily:
String key = "someKey";
String value1 = "someValue1";
String value2 = "someValue2";
Map<String, List<String>> map2 = new HashMap<>();
map2.computeIfAbsent(key, k -> new ArrayList<>()).add(value1);
map2.computeIfAbsent(key, k -> new ArrayList<>()).add(value2);
System.out.println(map2);
The documentation for Map.computeIfAbsent(...) has pretty much this example.
In map2 you need to add ArrayList (you declared it as Map<String, ArrayList<String>> - the second one is the value type) only, that's why it gives you incompatible types.
You would need to do initialize the key with an ArrayList and add objects to it later:
if (!map2.containsKey(key)) {
map2.put(key, new ArrayList<String>());
}
map2.get(key).add(value);
Or you could use Multimap from guava, then you can just map2.put and it won't overwrite your values there but add to a list.
You are little bit away from what you are trying to do.
Map<String, ArrayList<String>> map2 = new HashMap<String, ArrayList<String>>();
this will allow only String as key and an ArrayList as value. So you have to try something like:
ArrayList<String> value=new ArrayList<String>();
value.add("2");
value.add("3");
map2.put("1", value);
When retrieving you also have to follow ans opposite procedure.
ArrayList<String> valueTemp=map2.get("1");
then you can iterate over this ArrayList to get those values ("2" and "3");
Try like this. //use list or set.. but set avoids duplicates
Map<String, Set<String>> map = new HashMap<>();
Set<String> list = new HashSet<>();
// add value to the map
Boolean b = map.containsKey(key);
if (b) {
map.get(key).addAll(list);
} else
map.put(key, list);
}
You can not add different values in same key in Map. Map is override the value in that key. You can do like this way.
Map<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
ArrayList<String> list=new ArrayList<String>();
list.add("2");
list.add("3");
map.put("1", list);
first add value in array list then put into map.
It is all because standard Map implementations in java stores only single pairs (oneKey, oneValue). The only way to store multiple values for a particular key in a java standard Map is to store "collection" as value, then you need to access this collection (from Map) by key, and then use this collection "value" as regular collection, in your example as ArrayList. So you do not put something directly by map.put (except from creating the empty collection), instead you take the whole collection by key and use this collection.
You need something like Multimap, for example:
public class Multimap<T,S> {
Map<T, ArrayList<S>> map2 = new HashMap<T, ArrayList<S>>();
public void add(T key, S value) {
ArrayList<T> currentValuesForGivenKey = get(key);
if (currentValuesForGivenKey == null) {
currentValuesForGivenKey = new ArrayList<T>();
map2.get(key, currentValuesForGivenKey);
}
currentValuesForGivenKey.add(value);
}
public ArrayList<S> get(T key) {
ArrayList<String> currentValuesForGivenKey = map2.get(key);
if (currentValuesForGivenKey == null) {
currentValuesForGivenKey = new ArrayList<S>();
map2.get(key, currentValuesForGivenKey);
}
return currentValuesForGivenKey;
}
}
then you can use it like this:
Multimap<String,String> map2 = new Multimap<String,String>();
map2.add("1","2");
map2.add("1","3");
map2.add("1","4");
for (String value: map2.get("1")) {
System.out.println(value);
}
will print:
2
3
4
it gives error that says "incompatible types" and it can not be converted to ArrayList and it says the error is at the value part of the line.
because, it won't automatically convert to ArrayList.
You should add both the values to list and then put that list in map.

Java - Get map values by arrayList

I have question why I can't get this values
HashMap<String, P> users = new HashMap<String, P>();
users.put("john", new P("john"));
List<String> arenaUsers = new ArrayList<String>();
arenaUsers.add("john");
for (String user : arenaUsers) {
for (P p : users.get(user)) {
System.out.println(p.getName());
}
}
I got error:
Can only iterate over an array or an instance of java.lang.Iterable
But I can't iterate Map, How I can fix it?
here you class p does not implement Iterable so it can't be used inside the for loop. So to use it inside for loop you need to implement Iterable or use an existing collection which have already implemented Iterable i.e.
Map<String, List<String>> map = new HashMap<String, List<String>>();
List<String> l =new ArrayList<String>();l.add("stack");l.add("overflow");
map.put("trying", l);
for(String ss: map.get("trying")){
System.out.println(ss);
}
Here i have used List which implements Iterable and can be used in side the for loop.
In Map for one key you will get only one value, thats the cause of
"Can only iterate over an array or an instance of java.lang.Iterable"
this happens in the second for loop, which is useless as its only one value
for (P p : users.get(user))
Instead do as:
for (String user : arenaUsers) {
if(users.containsKey(user))
System.out.println(users.get(user).getName());
}
}

Appending data to a subarray instead of having it overwritten with the latest entry

I currently have a Map that is configured as such.
Map<String, ArrayList<Object>> map = new HashMap<String, ArrayList<Object>>();
where the purpose is to be able to have a setup much like the following:
array("foo"->array(1->"aaa",2->"bbb",3->"ccc"),
"bar"->array(1->"aaa",2->"bbb",3->"ccc"),
"bah"->array(1->"aaa",2->"bbb",3->"ccc"),
)
The problem I'm running into is that I can create the root array fine, but it will do the following, using the previous example as illustration
array("foo"->array(3->"ccc"),
"bar"->array(2->"bbb"),
"bah"->array(3->"ccc"),
)
What I'm trying to find out is how I can append the sub array as opposed to having it overwritten. I assume it's easily done I'm just missing something obvious.
What you need is to first check if map has an entry for a particular key. If not, then add an empty arraylist.
After that, get that arraylist from map and add object to that arraylist.
Map<String, ArrayList<Object>> map = new HashMap<String, ArrayList<Object>>();
String first = "FIRST";
if (map.get(first) == null){
map.put(first, new ArrayList<Object>());
}
map.get(first).add(new Object());
If you will print above map, you will get desired output.
Appending to Array's in Java is not possible because they have a fixed length. I suggest you use ArrayList instead.
HashMap<String, ArrayList<Object>> map = new HashMap<String, ArrayList<Object>>();
public void appendToMap(String key, Object o)
{
if(!map.containsKey(key))
{
map.put(key, new ArrayList<Object>());
}
map.get(key).add(o);
}
Afterwards just set your values:
appendToMap("foo", "aaa");
appendToMap("foo", "bbb");
// and so on...
You can just create a method to add to the sub-array, and create it if it doesn't exists :
Map<String, ArrayList<Object>> map = new HashMap<String, ArrayList<Object>>();
addToArray(map, "foo", "aaa");
addToArray(map, "foo", "bbb");
addToArray(map, "foo", "ccc");
addToArray(map, "bar", "aaa");
// ...
And the method would be :
private static void addToArray(final Map<String, ArrayList<Object>> map, final String key, final Object object) {
if (!map.containsKey(key))
map.put(key, new ArrayList<Object>());
map.get(key).add(object);
}
If you only need to store Strings in you array, you can use an ArrayList<String> instead of your ArrayList<Object>.
Switch to String instead of Object (if the list would always contain strings)
Map<String, List<String>> map = new HashMap<String, List<String>>();
Then add to your Map as follows
// check if a List already exists
if ((list = map.get("foo")) == null) { // if !exists,
list = new ArrayList<String>(1); // CREATE a new List
list.add("aaa");
map.put("foo", list); // ADD the new List to Map
} else { // if exists,
list.add("aaa"); // ADD to the existing List
}

Categories