I have this :
Map<Integer, String[]> strs = new HashMap<Integer, String[]>();
for (int population = 0 ; population < 20 ; population++) {
strs.put(0, morning_food);
strs.put(1, snack1_food);
strs.put(2, lunch_food);
strs.put(3, snack2_food);
strs.put(4, nite_food);
for (String[] value : strs.values()) {
for (String val : value) {
Log.d("", val);
}
}
}
this will display the content of strs for 20 times, how can I get first strs, or fourteenth strs or else? I have tried save it to array, but it always display the last strs whatever index I want, any solution? Thx
When you use Map.put it will override any value that has already been associated with the key. When you call Map.put(0, ...) 20 times, you still only have one value associated with the key 0, the most recent value passed to put.
If you need to store 20 distinct values associated with a single key, use Guava's Multimap.
Multimap
use LinkedHashMap if you want to loop through it in a set order
Related
Currently I have sorted my Hashmap on the values field.
I need to count the number of entries associated with each value in the hashmap.
Initially i thought of iterating over the sorted hashmap and counting the number of entries till the value did not change. In order to get the next value, I need to get to the next entry, but there is no way to do that till one loop iteration ends.
But I was just lost in the logic and could not proceed. :(
I tried the other logic which uses filters in stream().
Applying the filter on the values being 1 to 50 and then counting the entries which satisfy the predicate.
for(int i = 1; i < COUNT; i++){
int count = (int) single_count.entrySet().stream().filter(v -> v.getValue() == 1).count(); //collect(Collectors.toList());
unigram_Nc.put(i, count);
}
In this case I was aware of the values in the hashmap. But I would like to know the generic solution which returns the number of entries in a hashmap corresponding to each value.
Is there any other way to count the number of entries having a particular value without knowing the values before hand ?
You could do this much easier with the java 8 stream api.
For this you should take the values from your map: map.values()
With .stream() you get the stream for this collection.
then you can use the collect method with a groupingBy collector.
Finally it could look something like this:
final Map<Integer, Long> counts = map.values() // get the values
.stream() // get the stream
.collect(
Collectors.groupingBy( // the result should be grouped
o -> o, // the key of the result map is just the value
Collectors.counting() // the value of result map is the count
)
);
For older JDKs you can count like this:
Create a class and override its equals() and hashcode() method. Create a field of your preferred type say A and add another int type field to count.
1) Your hashcode() method should return the hash value of your field A.
2) In your equals() method, increase the value of count by 1 and set the count as value
Now create 2 hashmaps, first will have your initial map's value as keys. The second one will have the result of all the counts of values.
Refer to the below snippet:
class A
{
Integer count = 1;
String name;
#override
public int hashcode()
{
return name.hash();
}
#override
public boolean equals(Object obj)
{
obj.count++;
secondmap.put(obj.name, obj.count);
return true;
}
}
Now in your main class:
static firstmap = new ConcurrentMap<A, Integer>();
static secondmap = new ConcurrentMap<String, Integer>();
iterate over yourmap
{
put the value in firstmap as firstmap.put(yourmap value, 0);
}
At the end of iteration you will have all the count of values in the secondmap.
Note: If your initial map was having different signature then you can explicitly set the value of String name via A's constructor.
This was just an example, the actual implementation may differ a bit according your solution however you can refer to this logic. Also while creating your initial map you can implement this. This will save you the trouble of iterating again.
try this simple logic
Map<String,Integer> dataMap=new LinkedHashMap<String,Integer>(); //Your data map
Map<Integer,Integer> countMap=new LinkedHashMap<Integer,Integer>(); //map to count data map entries
//initializing with default value
dataMap.put("a", 1);
dataMap.put("b", 2);
dataMap.put("c", 1);
dataMap.put("d", 2);
dataMap.put("e", 1);
dataMap.put("f", 3);
dataMap.put("g", 1);
//main logic
dataMap.forEach( (k,v) -> {
if(countMap.get(v)==null)
countMap.put(v, 0);
Integer count=countMap.get(v);
countMap.put(v,count+1);
} );
//printing the count
countMap.forEach( (k,v) -> {
System.out.println(k+" "+v);
} );
I have this HashMap containing words and the count for each word from a given text file;
{word=1, word2=1, word3=2, word4=1, word5=1, word6=4, word7=1, word8=1};
i was following your suggestion in other topics; but i have notice that if use fro example sorted Collections and i search for a specific KEY which could be 1 in this case it only return me one word while instead can return more values for same key;
the point is between all the collections:
Lists
Maps
ArrayLists
Trees
HashMaps
HashTables
which is the most advisable to use?
on my Class the user will input an int and that int will correspond to the 1st or 2nd or 3rd or 4th and so on..... words used in the files base on the count and occurences;
it's challenging
so far i have managed to store in hashmap and eventually order it in a Tree by Desc Key; so first element will be the greater; but still the algorithm needs more sense;
ps. i do not expect solution or pieces of codes but a good input to start ... a very good advise or direction best to follow;
Maps, by nature, store (will return) only one element per key. That means that if you'll store [key:1, val:a] and then store again [key:1, val:2]. The second insertion will override the first and when you'll "get" key:1 the returned result will be b.
You can, however, to store a List per key. This list can store all the value values per the same key.
So we'll declare the map that we'l use as follows:
Map<String, LinkedList<String>> map = new HashMap<>();
This is how insert should look like:
public void insert(String key, String value){
List<String> values = map.get(key);
if (values == null){ // this is the first time we use this key
values = new LinkedList<String>(); // so we need to create a new values List
}
values.add(value);
map.put(key, values)
}
the "get" is pretty straightforward:you get the list of values and if it's not null - iterate the values and print/do whatever you want with them.
public List<String> get(String key){
return map.get(key);
}
If I understand you correctly, you have a Map<String,Integer> map; which maps words to their frequencies, and now you want to look up words by frequency.
Create a new map that Map<Integer,List<String>> and fill it using the first map:
Map<Integer,List<String>> reverseMap = new HashMap<>();
for (Map.Entry<String,Integer> entry : map.entrySet()) {
List<String> list = reverseMap.get(entry.getValue());
if (list == null) {
reverseMap.put(entry.getValue(), list = new ArrayList<>());
}
list.add(entry.getKey());
}
You will get a map like:
java.util.HashMap[3] {
1=[word2, word4, word, word5, word7, word8]
2=[word3]
4=[word6]
}
In this map, each key is the frequency, each value is a list of words having that frequency.
Edit: To pull out the words having the second-most used frequency ("rank 2"), generate a list of the most used frequencies:
List<Integer> frequencies = new ArrayList<>(reverseMap.keySet());
Collections.sort(frequencies, Collections.reverseOrder());
Then:
System.out.println(reverseMap.get(frequences.get(2 - 1)));
Or, to sort the entire map in descending order of frequency (4, 2, 1), declare it as a TreeMap instead of a HashMap, with a reverseOrder comparator:
Map<Integer,List<String>> reverseMap = new TreeMap<>(Collections.reverseOrder());
I have a HashMap.
Map<String,String> lhm = new HashMap<String,String>();
lhm.put("Zara", "biu");
lhm.put("Mahnaz", "nuios");
lhm.put("Ayan", "sdfe");
lhm.put("Daisy", "dfdfh");
lhm.put("Qadir", "qwe");
I want to sort that hashmap according to the sequence which is given in properties file.Actually that property entry will be having the keys in some order.My property entry will looks like this
seq=Ayan,Zara,Mahnaz,Qadir,Daisy
What I have tried towards this is
Map<String,String> lhm = new HashMap<String,String>();
Properties prop=new Properties();
prop.load(new FileInputStream("D:\\vignesh\\sample.properties"));
// Put elements to the map
lhm.put("Zara", "biu");
lhm.put("Mahnaz", "nuios");
lhm.put("Ayan", "sdfe");
lhm.put("Daisy", "dfdfh");
lhm.put("Qadir", "qwe");
// Get a set of the entries
Set<Entry<String, String>> set = lhm.entrySet();
// Get an iterator
Iterator<Entry<String, String>> iter = set.iterator();
// Display elements
String sequence=prop.getProperty("seq");
System.out.println("sequence got here is "+sequence);
String[] resultSequence=sequence.split(",");
for(int j=0;j<resultSequence.length;j++)
{
while(iter.hasNext()) {
Map.Entry me = (Map.Entry)iter.next();
String res=(String) me.getKey();
if(res.equals(resultSequence[j]))
{
System.out.println("values according with the sequence is "+lhm.get(resultSequence[j]));
}
}
}
The output which I'm getting after this is
sequence got here is Ayan,Zara,Mahnaz,Qadir,Daisy
values according with the sequence is sdfe
My expected output is
values according with the sequence is sdfe
values according with the sequence is biu
values according with the sequence is nuios
values according with the sequence is qwe
values according with the sequence is dfdfh
It is working for the first iteration in my for loop.After that it exits from my for loop also.What I'm missing here??Thanks for reading.
It's not working because you never reset your iterator. You only match the string on your first run. Try putting the iterator inside the loop, to get a new one for every iteration, like this:
for(int j=0;j<resultSequence.length;j++)
{
Iterator<Entry<String, String>> iter = set.iterator();
while(iter.hasNext()) {
....
}
}
You are complicating your task too much. In fact, you are just printing your values in sorted order, but not actually sorting them. Also, that's a pathetic way to implement sorting. You are iterating over your map as much number of times as there are strings in your sequence (Currently it's 5).
You should use a TreeMap instead, if you want to sort your keys. Here, you will need to pass custom Comparator, which will compare based on value in your property file.
Suppose you have order in a string:
String order = "Ayan,Zara,Mahnaz,Qadir,Daisy";
then your comparator would look like:
Comparator<String> comparator = new Comparator<String>() {
#Override
public int compare(String key1, String key2) {
return order.indexOf(key1) - order.indexOf(key2);
}
};
The comparator compares each key in the TreeMap based on it's index in the order string.
Now just pass this comparator to the overloaded TreeMap constructor.
SortedMap<String,String> lhm = new TreeMap<String,String>(comparator);
Now, whatever you insert in the map, will be sorted according to the order defined in property file.
To iterate over the map, you can use enhanced for loop:
for(Entry<String, String> entry : lhm.entrySet()) {
System.out.println(entry.getValue());
}
You should get iterator for each iteration of for loop:
...
for(int j=0;j<resultSequence.length;j++)
{
// Get an iterator
Iterator<Entry<String, String>> iter = set.iterator();
while(iter.hasNext()) {
...
Use a TreeMap. This allows you to write a custom comparator for sorting the entries.
HashMap does not save any order, I think you should use LinkedHashMap that iterates in same order that values were inserted.
I think that you don't need iterate with the while loop, once you get the ordered array with the keys from the properties file is enough to do this:
for (String key:resultSequence) {
String value = lhm.get(key);
System.out.println("values according with the sequence is "+ value);
}
Iterate over the keys of your property file. For each of them, get the element in your map, if it exists.
Your while loop only get executed only once , because the iterator doesn't hold any more values after it reached the last element . Instead of while iterator use
for each loop Or else create a new iterator inside for loop and try
Well as the other answers have shown your error which is not reseting the iterator, let me propose another way of doing what you are trying to achieve.
If you want to go through the entire list, intead of using an iterator and writing the usual while(iter.hasNext()){} loop you may want to consider using a for loop as in the following example :
Map<String,String> lhm = new HashMap<String,String>();
// Put elements to the map
lhm.put("Zara", "biu");
lhm.put("Mahnaz", "nuios");
lhm.put("Ayan", "sdfe");
lhm.put("Daisy", "dfdfh");
lhm.put("Qadir", "qwe");
for(Entry<String, String> e : lhm.entrySet()) {
// do something as the for loop iterates through your map.
// e being the current element.
}
I have multiple records received as string through a query. I want to store records having the same "long" key in a collection dynamically as I parse them in a loop. Like, insert key and value and if the key exists, it adds to the values and if not, a new key is created. What would be the most efficient way of doing this? I can do it using multiple arrays but I would prefer a cleaner way.
I cannot use a HashMap as I have to first store the records in an Array or ArrayList and then insert it which defeats the purpose as I have to group the lists by key first anyway. The no. of records will not more than 50 at a time.
E.g data:
for(i = 0; i < numRecords; i++ ) {
Data: 1 "A", 2 "B", 1 "C", 3 "D", 1 "E"
}
I want to have a collection where inside the loop I can just add: 1 "A" and so on..
I think Map<Long,List<String>> may help you.
Map<Long,List<String>> map = new HashMap<>();
...
if(map.get(key)!=null){
List<String> list = map.get(key);
list.add(value);
}else{
List<String> list = new ArrayList<>();
list.add(value);
map.put(key,list);
}
I'm sure this isn't a hugely complex problem but I'm relatively new to java and have been puzzling with this one for a while.
Say I have an array which contains 6 string values, and lets say they are: [Apple, Banana, Banana, Banana, Orange, Orange]. I am looking to build a method that will take this array and return a string, in the case above, as: "Apple, 3×Banana, 2×Orange".
I would greatly appreciate some help with this. I've been trying different techniques to achieve this but fall down on the correct behavior on the first iteration of the array and when to detect a repeated value ect.
Use Map<String, Integer>. Iterate over the array and put strings as Map key and counter as value:
Map<String, Integer> words = HashMap<String, Integer>();
for (String word : words) {
Integer count = words.get(word);
count = count == null ? 0 : count++;
words.put(word, count);
}
Now the words map contains mapping between word and its count.
You can use the TreeMap object where the Fruit name is the key and value is the number of times it has been seen.
You iterate through the array fruit by fruit, using say a foreach loop and update that fruit's value in the TreeMap. At the end you print the key and its value. Since we've used a TreeMap the keys will be in sorted order.
What have you tried ? Create instance of HashMap, where keys are fruits names and values are fruits occurrence. Iterate over your your array, on every iteration, add new fruit to your Map or increment the number of occurrence of existing key.
Then iterate over HashMap, and build your String
If everything is in a single ArrayList and you know the fruit that you are expecting you could use
ArrayList<String> fruits = new ArrayList<>();
//load some fruit code [ .. ]
int orangeOccurrences = Collections.frequency(fruits, "orange");
but Map is definitively the more correct approach.