java code
Hashtable<String, Integer> gettingStatus = searchActiveAssetStatus();
ArrayList<String> statusValue = new ArrayList<String>();
ArrayList<String> statusCount = new ArrayList<String>();
Set<String> keys = gettingStatus.keySet();
for (String key : keys) {
if (key.contains("Active")) {
statusValue.add(key);
}
if (key.contains("Abandoned")) {
statusValue.add(key);
}
if (key.contains("Deleted")) {
statusValue.add(key);
}
}
for the above i have stored Key in an separate array list (available), at the same time if that key exist in hashtable i want to store the value for that corresponding key in another array list (statusCount) how?
You may use the entrySet() method instead of the keySet() method:
Set<Entry<String, Integer>> entries = gettingStatus.entrySet();
for (Entry<String, Integer> entry : entries) {
String key = entry.getKey();
Integer value = entry.getValue();
if (key.contains("Active")) {
statusValue.add(key);
// Store value
}
if (key.contains("Abandoned")) {
statusValue.add(key);
// Store value
}
if (key.contains("Deleted")) {
statusValue.add(key);
// Store value
}
}
If I got your question right you just have to ask for the value of the corresponding key and put it in the list:
Hashtable<String, Integer> gettingStatus = searchActiveAssetStatus();
ArrayList<String> statusValue = new ArrayList<String>();
ArrayList<String> statusCount = new ArrayList<String>();
Set<String> keys = gettingStatus.keySet();
for (String key : keys) {
if (key.contains("Active") || key.contains("Abandoned") || key.contains("Deleted")) {
statusValue.add(key);
statusCount.add(gettingStatus.get(key).toString());
}
}
Or as Benjamin said just take entrySet() which makes it even easier.
Related
I have a data structure as follows:
Map<String,ArrayList<String>> graph = new HashMap<String,ArrayList<String>>();
This is essentially a hash map which puts string values as keys and stores array list of strings in the value for the keys.
Now I am trying to reverse the key value pattern to make value the key and key the value. The way I am doing it is as follows:
private Map<String,ArrayList<String>> reverseAdjList(Map<String,ArrayList<String>> adjList){
Map<String,ArrayList<String>> tGraph = new HashMap<String,ArrayList<String>>();
for (Map.Entry<String, ArrayList<String>> entry : adjList.entrySet()) {
String key = entry.getKey();
ArrayList<String> values = new ArrayList<>();
values.add(key);
ArrayList<String> value = entry.getValue();
for(String v:value){
if(tGraph.containsKey(v)){
values.addAll(tGraph.get(v));
}
tGraph.put(v, values);
}
}
return tGraph;
}
So this works for me in reversing the hash map keys values pattern for small data set however when I try it on a larger dataset I run into
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:261)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
at java.util.ArrayList.addAll(ArrayList.java:579)
at GraphProcessor.reverseAdjList(GraphProcessor.java:67)
at GraphProcessor.SCC(GraphProcessor.java:135)
at GraphProcessor.<init>(GraphProcessor.java:50)
at GraphProcessor.main(GraphProcessor.java:250)
I know this is a very naïve and wrong approach to do it, what is a better and correct way to do it?
There's a bug in your code:
for (Map.Entry<String, ArrayList<String>> entry : adjList.entrySet()) {
String key = entry.getKey();
ArrayList<String> values = new ArrayList<>(); // Wrong place for this variable.
values.add(key);
ArrayList<String> value = entry.getValue();
for(String v:value){
if(tGraph.containsKey(v)){
values.addAll(tGraph.get(v));
}
tGraph.put(v, values);
}
}
The local variable values should be in the nested for loop, otherwise values are accumulated for all later new key v and will cost a lot of memory if your dataset is large, it should be:
private Map<String, ArrayList<String>> reverseAdjList(Map<String, List<String>> adjList) {
Map<String, ArrayList<String>> tGraph = new HashMap<>();
for (Map.Entry<String, List<String>> entry : adjList.entrySet()) {
String key = entry.getKey();
List<String> value = entry.getValue();
for (String v : value) {
ArrayList<String> values = new ArrayList<>();
values.add(key);
if (tGraph.containsKey(v)) {
values.addAll(tGraph.get(v));
}
tGraph.put(v, values);
}
}
return tGraph;
}
But actually you don't need to create a new List instance for each inner for step, try the following code with JDK 1.8:
private Map<String, List<String>> reverseMap(Map<String, List<String>> adjList) {
Map<String, List<String>> tGraph = new HashMap<>();
for (Map.Entry<String, List<String>> entry : adjList.entrySet()) {
for (String value : entry.getValue()) {
tGraph.computeIfAbsent(value, v -> new ArrayList<>()).add(entry.getKey()); // Updated according comment from #shmosel
}
}
return tGraph;
}
If you're using older version of jdk, you can try:
private Map<String, List<String>> reverseMap(Map<String, List<String>> adjList) {
Map<String, List<String>> tGraph = new HashMap<>();
for (Map.Entry<String, List<String>> entry : adjList.entrySet()) {
for (String value : entry.getValue()) {
List<String> newValues = tGraph.get(value);
if (newValues == null) {
newValues = new ArrayList<>();
tGraph.put(value, newValues);
}
newValues.add(entry.getKey());
}
}
return tGraph;
}
Hope this could be helpful :-)
I have a hashmap which has a list of keys which i am interating in a for loop.
In my Hashmap i have one Key FURNITURE_NAMES and values as Table,Chair,Board.
Now i want the values that are present in key for FURNITURE_NAMES be stored in a list.
Below is the code i have done:
When i get the key FURNITURE_NAMES i have the below values
FURNITURE_NAMES = "table,chair,board"
for(Map.Entry<String, List<String>> entry : furnitureMap.entrySet())
{
String furnitureKey = entry.getKey();
for(String key : entry.getValue() )
{
if(furnitureKey!=null && furnitureKey.equalsIgnoreCase("FURNITURE_NAMES"))
{
furnitureList = new ArrayList<String>();
String a = new String();
a=key;
furnitureList.add(a);
}
}
}
When i iterate the Hashmap get the key FURNITURE_NAMES i get the first value "Table"
That value gets stored in the list.
Second i get chair.
It overrides value Table and i still have only 1 value in the list that is chair.
I tried to put the values in the list through index also but it threw indexoutofboundsexception. How do i have all the values in the list instead of getting overridden by new values. Any help.
At each iteration you create a new instance of the list as follows:
furnitureList = new ArrayList<String>();
You have to create this list before the for or somewhere else and leave it like that as follows:
furnitureList = new ArrayList<String>();
for(Map.Entry<String, List<String>> entry : furnitureMap.entrySet()) {
// same code here except the list initialization
}
Also, you don't need to create a new String for each value. Just put it in the list as the the value variable (which is incorrectly named key :) ) from the for loop. If we refactor your code it would look something like:
furnitureList = new ArrayList<String>();
for(Map.Entry<String, List<String>> entry : furnitureMap.entrySet()) {
if(entry.getKey() != null && entry.getKey().equalsIgnoreCase("FURNITURE_NAMES")) {
furnitureList.addAll(entry.getValue());
}
}
For every iteration you are doing
furnitureList = new ArrayList<String>();
which is re-initialising your list.
Move it to before your first for loop
e.g.
furnitureList = new ArrayList<String>();
for(Map.Entry<String, List<String>> entry : furnitureMap.entrySet())
it should be, list should be created before iterating over the map value(ie., list) and creation of string a is not required, it can be directly added to list or you feel to clone try to String newKey=new String(key);
furnitureList = new ArrayList<String>();
for(Map.Entry<String, List<String>> entry : furnitureMap.entrySet())
{
String furnitureKey = entry.getKey();
for(String key : entry.getValue() )
{
if(furnitureKey!=null && furnitureKey.equalsIgnoreCase("FURNITURE_NAMES"))
{
furnitureList.add(key);
}
}
}
for second entry of idAndTags the inner-map is shuffled but not for the first
FIRST APPROACH!
for (Map.Entry<String, Map<String, String>> entryOne : idAndTags.entrySet()) {
List keys = new ArrayList(entryOne.getValue().keySet());
System.out.println(keys);
Collections.shuffle(keys);
System.out.println(keys);
}
SECOND APPROACH!
for (Map.Entry<String, Map<String, String>> entryOne : idAndTags.entrySet()) {
shufTags = new HashMap<String, String>();
Map<String, String> tags = entryOne.getValue();
System.out.println(tags);
final List<String> vs = new ArrayList<String>(tags.values());
Collections.shuffle(vs);
final Iterator<String> vIter = vs.iterator();
for (String k : tags.keySet())
shufTags.put(k, vIter.next());
System.out.println(shufTags);
}
Map#.keySet() returns a view of the key set, which doesn't support ordering. Shuffling it has no effect on the map.
You can not change the order of iteration of a HashMap, but a LinkedHashMap iterates itself in the order of insertion, so you can replace the inner maps with a LinkedHashMap and use a shuffled key set to drive the insertion.
didn't have a choice, solved it like this... seems to work for me!
Map<String, Map<String, String>> _idAndTagsShuffled = new HashMap<String, Map<String, String>>();
for (Map.Entry<String, Map<String, String>> entryOne : _idAndTags.entrySet()) {
ArrayList<String> keys = new ArrayList(entryOne.getValue().keySet());
shuffledMap = new HashMap<String, String>();
do {
shuffled = new ArrayList<String>();
Collections.shuffle(keys);
for (String key : keys) {
shuffled.add(key);
}
int count = 0;
isShuffled = false;
for (String tag : entryOne.getValue().keySet()) {
if (!tag.equals(shuffled.get(count))) {
isShuffled = true;
}
count++;
}
} while (!isShuffled);
_idAndTagsShuffled.put(entryOne.getKey(), shuffledMap);
}
I have a HashMap<String, LinkedList<Integer>> and I want to create a hashMapInverted<LinkedList<Integer>, Set<String>> which contains in keys the lists, values of first map, and the values the set of strings which have the same list in first map.
How can I do this?
You can do:
Map<LinkedList<Integer>, Set<String>> mapInverted = new HashMap<>(myMap.size());
for(Entry<<String, LinkedList<Integer>> entry : myMap.entrySet()) {
String key = entry.getKey();
LinkedList<Integer> list = entry.getValue();
Set<String> strings = mapInverted.get(list);
if(strings == null) { // the list has not already been put in the map
strings = new HashSet<String>(); // create a new set
mapInverted.put(list, strings); // put the list and the new set
}
strings.add(key);
}
You can try -
Map<String, LinkedList<Integer>> map =new HashMap<String, LinkedList<Integer>>();
Map<LinkedList<Integer>, Set<String>> invertMap = new HashMap<LinkedList<Integer>, Set<String>>();
for (Entry<String, LinkedList<Integer>> entry : map.entrySet()) {
if(invertMap.containsKey(entry.getValue())){
invertMap.get(entry.getValue()).add(entry.getKey());
}else{
Set<String> set = new HashSet<String>();
set.add(entry.getKey());
invertMap.put(entry.getValue(), set);
}
}
I want to iterate over the HashMap list and retrieve the key and the values (value 1 and value2). There is a error at this line that says
"Type mismatch: cannot convert from element type Object to Map.Entry>"
for (Map.Entry<String, List<String>> entry : Map.entrySet())
Am I doing anything wrong. Please help me out. Here is the entire code.
public static void main(String[] args) {
Map<String, List<String>> conceptMap = new HashMap<String, List<String>>();
Map<String, List<String>> PropertyMap = new HashMap<String, List<String>>();
try{
Scanner scanner = new Scanner(new FileReader("C:/"));
while (scanner.hasNextLine()){
String nextLine = scanner.nextLine();
String [] column = nextLine.split(":");
if (column[0].equals ("Property")){
if (column.length == 4) {
PropertyMap.put(column [1], Arrays.asList(column[2], column[3]));
}
else {
conceptMap.put (column [1], Arrays.asList (column[2], column[3]));
}
}
for (Map.Entry<String, List<String>> entry : Map.entrySet()) {
String key = entry.getKey();
List<String> valueList = entry.getValue();
System.out.println("Key: " + key);
System.out.print("Values: ");
for (String s : valueList) {
System.out.print(s + " ");
}
}
}
scanner.close();
}
catch (Exception e) {
e.printStackTrace();
}
Change Map.entrySet() to PropertyMap.entrySet() or conceptMap.entrySet()
The Map.entrySet() method declared by the Map interface returns a collection-view of the map (returns a Set). Each of these set elements is a Map.Entry object. The only way to obtain a reference to a map entry is from the iterator of this collection-view.
If you want to return a Set you inserted into the map, you have to call it on the Collection you placed it in:
PropertyMap.entrySet() and conceptMap.entrySet() will return Sets.
Map.entrySet() is not calling the method on either of your instantiated Maps.
Map.entrySet() returns a collection view of the map.change it in to conceptMap.entrySet() or
propertyMap.entrySet