Merging a Set and List to HashMap - java

I have one set whose keys are String and List of type String I want to make a HashMap out of this Set and List. The set contains categories and the list contains places belonging to those categories. Following is what I tried
Set<Entry<String, Integer>> setUserPreferences = sortedUserPreferences.entrySet();
Map<String , Integer> sortedPlaces = new HashMap<String, Integer>();
List<String> topPlaces = new ArrayList<String>();
Map<String , List<String>> finalPlaces = new HashMap<String, List<String>>();
for (Entry<String, Integer> entry : setUserPreferences) {
sortedPlaces = placesService.sortPlaces(categorisedPlaces.get(entry.getKey()));
int counter = 0;
for (Map.Entry<String, Integer> sortedplace : sortedPlaces.entrySet()) {
topPlaces.add(sortedplace.getKey());
counter++;
if(counter == 5){
sortedPlaces.clear();
break;
}
}
finalPlaces.put(entry.getKey(), topPlaces);
topPlaces.clear();
}
First I iterate over the set and for each key I get the sorted Places, out of the sorted places I pick the top 5 places for each category, Finally I put it in the map where the key is the category and value is the list of top 5 places in that category.
I need to clear the topPlaces list for each iteration over the set because I dont want to have the places from one category appear in the other, but once I put the list in map(finalPlaces) and clear the list it also clear the map values.
How can I clear the list without clearing the map values.
Thanks

topPlaces is a reference to an Object, not a primitive. So, if you store it in the map, you have two references to the same Object, one inside the Map and one outside. If you wipe one, you wipe both.
If you want to clear topPlaces without deleting the stored list, you need to copy it before adding it to the Map.
Something like this:
finalPlaces.put(entry.getKey(), new ArrayList<String(topPlaces));

Related

How to remove an element from a HashMap with multiple keys in JAVA

In my system an element from a HashMap have multiple keys, like an element "chess" have the keys "board", "game", "strategy". I want to remove the element chess and every key pointing to him.
For example, thats the map: private Map<String, Artigo> listaArtigos = new HashMap<String, Artigo>();
The Artigo a1 have the keys "nasa", "space", "mars". I need to delete a1 and all his keys, cuz i think that every time i set an new map ("nasa", a1), it creates a new a1 with a new key, right? Like in this case i have 3 a1's in my map?
private Map<String, Artigo> listaArtigos = new HashMap<String, Artigo>();
//for your example from above
listaArtigos.remove("nasa", a1);

Store the values without overwriting

I have a Map<String, Integer> e.g.
"aaa", 1
"bbb", 2
"ccc", 3
"aaa", 4
The problem is that the HashMap does not store all key and values, as I've understood, when i try add the last pair ("aaa", 4), it will not be added, instead of this, the value for "aaa" (I mean 1) will be overwritten on 4.
I know, that I could create class, where I could store these pairs, but I need another solution. (without creating a new class)
EDIT ------------------------------------
Actually I have much more pairs, and I do not have uniques String or Integers, I mean that, if even I have two similar pairs they will be stored
A map, by definition, will have distinct keys. If you add a key-value pair and the key already exists, the new key-value pair will overwrite the existing key-value pair.
For your scenario, when you have multiple values against a single key, you can explore the following options
Option 1 : Since your key-value pairs are not unique, it can be stored as list of pairs. For every key-value pair, you can create a pair and insert it into the list.
List<Pair<String, Integer>> data = new ArrayList();
Pair<String, Integer> item = new Pair("abc", 1);
data.add(item);
This option does not give you optimized lookup capabilities that comes with Map.
Option 2. Create a Map<String, List<Integer>>. You'll not be able to do simple put operations on the map anymore, but you will be able to store all the items corresponding to each key without loss of information as well as retrieve them faster.
Create a List:
if (!map.containsKey("aaaa")) {
map.put("aaaa", new ArrayList<Integer>());
}
List<Integer> aaaaValues = map.get("aaaa");
aaaaValues.add(1);
aaaaValues.add(4);
...
If your values are unieque, use them as keys.
You don't have to create class. You can use List<org.apache.commons.lang3.tuple.Pair<String, Integer>>
Also one way, override equals and hashCode where you speak that object is unique only if String and Integer parameter is unique in pair
Map<String, Integer> map = new HashMap<String, Integer>(){
#Override
public boolean equals(Object o)
{
// your realization
}
#Override
public int hashCode()
{
// your realization
}
};

Java 8 filter List of Map objects based on Map property to remove some duplicates

Have a
List<Map<String, Object>> allPoints = new LinkedList<>();
Each map contains a "name" key with a String value;
Need to create a
List<Map<String, Object>> expectedPoints
There are duplicate names in the list; for these, want to keep the last one only.
E.g. if the list has three items, and first and third items both have"name" with value "abc", the resulting list should only contain the second and third items from the original list.
One way to do it is by using an auxiliary map:
Map<String, Map<String, Object>> map = new LinkedHashMap<>(allPoints.size(), 0.75f, true);
allPoints.forEach(point -> map.put((String)point.get("name"), point));
List<Map<String, Object>> expectedPoints = new ArrayList<>(map.values());
This works because Map.put either puts a new entry to the map or overwrites the value of an existing entry with the new one, thus keeping only the last point associated with the name.
I'm creating an access-ordered LinkedHashMap by using its overloaded constructor. This is to maintain the same order as in the allPoints list.
In case you have the constraint on one or more key-value pairs and flexible to use a Set, write your own Comparator and use descendingIterator on LinkedList and write to TreeSet. See code below:
LinkedList<Map<String, Object>> allPoints = new LinkedList<>();
Set<Map<String, Object>> expectedPoints = new TreeSet<>((objectMap1, objectMap2) ->
objectMap2.get("name").equals(objectMap1.get("name")) ? 0 : -1
);
allPoints.descendingIterator().forEachRemaining(expectedPoints::add);

Removing duplicate linked value from ArrayList java

we are facing a challenge in implementing one of our client requirement, using java as code technology.
we need to format the input given by the system, to display the data in a userfriendly format.
below is the data as input to our program.
its a java map with key as string and value as a list of strings
OP1004=[],
OP1006=[OP1004]
OP1005=[OP1003]
OP1009=[OP1006, OP1044, OP1046, OP1004],
OP1016=[OP1008, OP1009, OP1044, OP1005, OP1004],
output we are expecting as below.
OP1004=[],
OP1006=[OP1004]
OP1005=[OP1003]
OP1009=[OP1006, OP1044, OP1046], //here 1004 is deleted
OP1016=[OP1008, OP1009, OP1005, OP1004], //here 1044 is deleted
here, if we observe closely, we want to delete the repeated values from the list, that is
if we go thru the bottom, that is OP1016 contains the list as OP1008, OP1009 etc.. where OP1009 also has the list as OP1006, OP1044 etc.. where OP1006 again has the list as OP1004
so here we want to delete OP1004 from OP1009 because its already mapped to other(OP1006) OPID which is part of OP1009.
actually we are displaying this in a hierachy/flowchart diagram, so we want to delete duplicate navigation to the items.
Please help us in providing solution. appreciate your help in advance.
Thanks
Your problem boils down to checking whether elements of a list are present in other lists but these list are present in a map so you need to maintain the key-value pair.
This is how you can achieve that.
Loop over map and get the key and list of values, add a condition to check whether list is empty and contains more than 1 values.
Loop over same map again, get the key and add a condition to check whether the first loop key is equal to second loop key this is to avoid checking for same list. Add one more condition to check whether list is empty and contains more than 1 values.
Now you can remove elements from a list if those elements are present in another list by using List.removeAll() method.
Sample code
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Example {
public static void main(String[] args) {
List<String> firstList = new ArrayList<String>();
firstList.add("");
List<String> secondList = new ArrayList<String>();
secondList.add("OP1004");
List<String> thirdList = new ArrayList<String>();
thirdList.add("OP1003");
List<String> fourthList = new ArrayList<String>();
fourthList.add("OP1006");
fourthList.add("OP1044");
fourthList.add("OP1046");
List<String> fifthList = new ArrayList<String>();
fifthList.add("OP1008");
fifthList.add("OP1009");
fifthList.add("OP1044");
fifthList.add("OP1005");
fifthList.add("OP1004");
Map<String, List<String>> map = new HashMap<String, List<String>>();
map.put("OP1004", firstList);
map.put("OP1006", secondList);
map.put("OP1005", thirdList);
map.put("OP1009", fourthList);
map.put("OP1016", fifthList);
for (Map.Entry<String, List<String>> keyAndValue: map.entrySet()) {
String key = keyAndValue.getKey();
List<String> values = keyAndValue.getValue();
if (values.isEmpty() || (values.size() < 2)){
continue;
}
for (Map.Entry<String, List<String>> mapKeyAndValue: map.entrySet()) {
String key1 = mapKeyAndValue.getKey();
if (key.equals(key1)){
continue;
}
List<String> values2 = mapKeyAndValue.getValue();
if (values2.isEmpty() || (values2.size() < 2)){
continue;
}
values2.removeAll(values);
}
}
for (Map.Entry<String, List<String>> keyAndValue: map.entrySet()) {
System.out.println("Key is " + keyAndValue.getKey() + " Values are " + keyAndValue.getValue());
}
}
}
Check Output Here
Key is OP1004 Values are []
Key is OP1006 Values are [OP1004]
Key is OP1005 Values are [OP1003]
Key is OP1009 Values are [OP1006, OP1044, OP1046]
Key is OP1016 Values are [OP1008, OP1009, OP1005, OP1004]
Note - I assumed that you are using HashMap as you didn't specify what kind of map you are using and if you want the map to be ordered then use LinkedHashMap
as HashMap does not store elements in order.
A simple solution would be to change the
Map<String, List<String>> to Map <String<Set<String>>
Let me explain it in a better way:
List list = map.get(str);
Set<String> set = new HashSet<>();
set.addAll(list);
list.clear();
list.addAll(set);
now you can use it in the way you want..
Let me know if you didnt understand any part of it
Pseudo-code: if key exists then remove it from any values (of other keys)
for (String key : map.keySet()){ // iterate through all keys
for (Map.Entry<String, List> mapEntry : map.entrySet()){ // again iterate but this time get Map.Entry
if (!mapEntry.getKey().equals(key)){ // if entry is for other key
((List)mapEntry.getValue()).remove(key); // then remove key from list
// if this map cannot be modified you can keep key, mapEntry in another map here...
}
}
}
Create a set to hold all the values previously displayed. If an item can not be added to this set, then do not add it at all.
Map<String, String[]> original = ...
Set<String> used = new HashSet<>();
Map<String, String[]> reduced = original
.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
entry -> Arrays.stream(entry.getValue())
.filter(used::add)
.toArray(String[]::new)));

Using a hashmap to iterate over a list of hashmaps

I am using a hashmap to add similar values for each aclLine processed
for (String aclLine : refinedFileContents){
if(Some condition)
{
staticVariablesMap.put("lineNumber", **lineNumber**);
staticVariablesMap.put("**srcHostName**", batchBean.getSourceIpAddress());
staticVariablesMap.put("batchBean", batchBean);
}
}
Later I want to iterate over these hashmaps for each line and perform some actions specific to a given key, value pair (e.g. get the srcHostName for that lineNumber) and use it to process next steps. How can I iterate over these collected hashmaps for each srcHostName entry in the hashmap? Should I use ArrayList/List to store each instance of the hashmap? Is this feasible?
Sounds to me like you should combine the attributes in your hashmaps into an object instead. Then you could just use one hash map.
public class AclLine {
private long lineNumber;
private String srcHostName;
private Object batchBean;
}
Map<AclLine> lines = new HashMap<AclLine>();
// Or maybe a List?
List<AclLine> lines = new ArrayList<AclLine>();
Or is there a reason you need these "parallel" map entries?
I didn't get your question completely like you are putting values in only one hash map & you want to iterate hashmaps
You can iterate hash map like this.
Iterator<Entry<String, Object>> it = hashMap.entrySet().iterator();
while (it.hasNext())
{
Map.Entry<String, Object> entry = (Map.Entry<String, Object>)it.next();
}

Categories

Resources