This question already has answers here:
Closed 11 years ago.
Got the solution.. Used linkedHashMap and was able to store the sorted key values in an array. Here's the link for the code.
Possible Duplicate:
store key values of sorted hashmap in string[]
I created a hashmap and then 'sorted by value' the elements in the map using this code.
The code worked and i was able to display on screen the key value pairs sorted by value.
Now I want to store the keys(from the sorted elements) in a String[]. HashMap.keySet().toArray() doesn't help as the entired HashMap are not sorted.
Can anyone please suggest a method to do this?
further clarifying the situation - Suppose I have key value pairs like (a,1)(b,23)(c,7)
by using the above link, i was able to get (a,1)(c,7)(b,23) as output. I want to store {a,c,b} as a string array.
I hope the problem is clear now.
Reusing this code you would just use
List keys = sortByValue(m);
String[] keyArray = keys.toArray(new String[keys.size()]);
Using generics would make this nicer. I would also sort by Map.Entry (from entrySet()) which would be faster and simpler.
Sorting my keys is simple, use TreeMap.
TreepMap sortedMap = new TreeMap(someHashMap);
String[] sortedKeys = sortedMap.keySet().toArray();
That code is not really sorting the HashMap - it is merely returning the keys, sorted by their value:
So all you need is:
Object[] key_array = sortByValue(m).toArray();
I'd go either for something like
private static String[] keysSortedByValue(final Map<String, String> m) {
final String[] result = m.keySet().toArray(new String[m.size()]);
Arrays.sort(result, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
final String v1 = m.get(o1);
final String v2 = m.get(o2);
if (v1==v2) return 0;
if (v1==null) return -1;
if (v2==null) return +1;
return v1.compareTo(v2);
}
});
return result;
}
or use Map.Entry[] for greater efficiency (avoiding the lookup).
I would use Google Collection:
Map<String, String> map = new HashMap<String, String>( );
map.put("ABC1", "VALUE1");
map.put("ABC7", "VALUE1");
map.put("ABC2", "VALUE2");
map.put("ABC3", "VALUE1");
Multimap multimap = TreeMultimap.create();
for(Map.Entry<String, String> entry: map.entrySet() ) {
multimap.put( entry.getValue(), entry.getKey() );
}
System.out.println( Arrays.toString( multimap.values().toArray() ));
Related
I have created a map called result.
In the sortByKeys method as my keys are String with Numeric values, I have converted them to Integer key type Map then sorted them.
The sorting is working fine when I am looping and printing individually, but not when I am setting them in another Map.
public class TestDate {
public static void main (String args[]){
Map<String, String> result = new HashMap<String, String>();
result.put("error", "10");
result.put("1","hii");
result.put("Update","herii");
result.put("insert","insert");
result.put("10","hiiuu");
result.put("7","hii");
result.put("21","hii");
result.put("15","hii");
Map<String, String> sorted = sortByKeys(result);
//System.out.println(sorted);
}
private static Map<String, String> sortByKeys(Map<String, String> map) {
Map <Integer,String> unSorted = new HashMap<Integer, String>();
Map <String,String> sorted = new HashMap<String, String>();
for (Map.Entry<String, String> entry : map.entrySet())
{
try{
int foo = Integer.parseInt(entry.getKey());
unSorted.put(foo, entry.getValue());
}catch (Exception e){
}
}
Map<Integer, String> newMap = new TreeMap<Integer, String>(unSorted);
Set set = newMap.entrySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
Map.Entry me = (Map.Entry)iterator.next();
System.out.println(me.getKey());
System.out.println(me.getValue());
sorted.put(me.getKey().toString(), me.getValue().toString());
}
System.out.println(sorted);
return null;
}
}
Here is the o/p :
1
hii
7
hii
10
hiiuu
15
hii
21
hii
{21=hii, 10=hiiuu, 1=hii, 7=hii, 15=hii}
If you don't need the last inch of performance, you can solve this rather directly, without an extra step to sort the map, by using SortedMap:
Map<String,String> result = new TreeMap<>(Comparator.comparingInt(Integer::parseInt));
If you are among the unfortunate bunch who are still being denied access to Java 8, you'll have to implement the Comparator in long-hand:
new TreeMap<>(new Comparator<String,String> { public int compare(String a, String b) {
return Integer.compare(Integer.parseInt(a), Integer.parseInt(b));
}});
The above approach works only under the assumption that all keys are parseable integers. If that is not the case, then you won't be able to use the SortedMap directly, but transform your original map into it, filtering out the unparseable keys.
It's because the Map you're putting them into is a HashMap, which isn't sorted. There's no guarantee of the ordering of results you'll get out of the HashMap, even if you put them in in the right order.
(And calling it sorted doesn't change anything :) )
You print 2 different maps and not the same: you iterate over and print the entries of newMap map, and at the end you print sorted map.
You see the sorted entries printed because you iterate over your sorted newMap.
Then you print the sorted map which is unsorted (despite by its name). You print a different map instance.
Print this:
System.out.println(newMap); // This is the instance of the sorted "TreeMap"
This question already has answers here:
Partial search in HashMap
(5 answers)
Closed 6 years ago.
I am currently using HashMap<String, Integer> which is filled with keys of type String which are all, let's say, 5 chars long. How can I search for an specific key of 4 chars or less, which is part and at the beginning of some other keys and get all hits as a collection of <Key, Value>?
Iterate is your only option unless you create a custom data structure:
for (Entry<String, Integer> e : map.entrySet()) {
if (e.getKey().startsWith("xxxx")) {
//add to my result list
}
}
If you need something more time efficient then you'd need an implementation of map where you are tracking these partial keys.
It seems like a use case for TreeMap rather than HashMap. The difference is that TreeMap preserves order. So you can find your partial match much quicker. You don't have to go through the whole map.
Check this question Partial search in HashMap
You cannot do this via HashMap, you should write your own implementation for Map for implementing string length based searching in a map.
Map<String, Integer> result = new HashMap<String, Integer>;
for(String key : yourMap.keySet()) {
if(key.length() == 4){
result.put(key, yourMap.get(key);
}
}
After executing this code you have all key/value pairs with 4 letter keys in result.
Set<Entry<String, Integer>> s1 = map.entrySet();
for (Entry<String, Integer> entry : s1) {
if(entry.getKey().length == 4)
//add it to a map;
}
First get the entry set to your hashmap. Iterate through the set and check the length of each key and add it to a map or use it as u want it.
With HashMap<String, Integer> you can only go through keySet() and do contains() for String keys and your pattern.
As has been noted, there isn't a terribly efficient* way to do it with the datastructure you have specified. However, if you add an additional Map<Integer, List<String>> to keep track of the mapping from string length to the list of all keys with that length, then you will be able to do this very efficiently.
*Using just the Map<String, Integer>, you would need to iterate through the entire capacity of the larger map, whereas adding this supplemental datastructure would impose an O(1) lookup (assuming you used a HashMap) followed by iteration through just the result set, which is the fastest possible outcome.
You can try this approach:
public Map<String,Integer> filterMap(Map<String, Integer> inputMap){
Map<String, Integer> resultHashMap = new HashMap<String, Integer>();
for (String key : inputMap.keySet()) {
if(key.length()==5){
resultHashMap.put(key,inputMap.get(key));
}
}
return resultHashMap;
}
Good day, this is kind of confusing me now(brain freeze!) and seem to be missing something. Have an ArrayList which i populate with a HashMap. now i put in my HashMap and arraylist.
Map.put(DATE, value1);
Map.put(VALUE, value2);
arraylist.put(Map);
Since am parsing a JSON, the arraylist increases in significant size. now my question is how do you get the values from both map keys in the arraylist? i have tried this
if(!list.isEmpty()){ // list is an ArrayList
for(int k = 0; k < list.size(); k++){
map = (HashMap)list.get(k);
}
}
Log.d(TAG, "map size is" + map.size());
String [] keys = new String[map.size()];
String [] date_value = new String[map.size()];
String [] value_values = new String[map.size()];
int i = 0;
Set entries = map.entrySet();
Iterator iterator = entries.iterator();
while(iterator.hasNext()){
Map.Entry mapping = (Map.Entry)iterator.next();
keys[i] = mapping.getKey().toString();
date_value[i] = map.get(keys[i]);
if(keys[i].equals(DATE)){
date_value[i] = map.get(keys[i]);
} else if(keys[i].equals(VALUE)){
value_values[i] = map.get(keys[i]);
}
i++;
}
But i can't seem to get all the values. the Map size always return a value of 2, which is just the elements. how can i get all the values from the Map keys in the ArrayList? Thanks
Why do you want to re-invent the wheel, when you already have something to do your work. Map.keySet() method gives you a Set of all the keys in the Map.
Map<String, Integer> map = new HashMap<String, Integer>();
for (String key: map.keySet()) {
System.out.println("key : " + key);
System.out.println("value : " + map.get(key));
}
Also, your 1st for-loop looks odd to me: -
for(int k = 0; k < list.size(); k++){
map = (HashMap)list.get(k);
}
You are iterating over your list, and assigning each element to the same reference - map, which will overwrite all the previous values.. All you will be having is the last map in your list.
EDIT: -
You can also use entrySet if you want both key and value for your map. That would be better bet for you: -
Map<String, Integer> map = new HashMap<String, Integer>();
for(Entry<String, Integer> entry: map.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
P.S.: -
Your code looks jumbled to me. I would suggest, keep that code aside, and think about your design one more time. For now, as the code stands, it is very difficult to understand what its trying to do.
List constructor accepts any data structure that implements Collection interface to be used to build a list.
To get all the keys from a hash map to a list:
Map<String, Integer> map = new HashMap<String, Integer>();
List<String> keys = new ArrayList<>(map.keySet());
To get all the values from a hash map to a list:
Map<String, Integer> map = new HashMap<String, Integer>();
List<Integer> values = new ArrayList<>(map.values());
Try it this way...
I am considering the HashMap with key and value of type String, HashMap<String,String>
HashMap<String,String> hmap = new HashMap<String,String>();
hmap.put("key1","Val1");
hmap.put("key2","Val2");
ArrayList<String> arList = new ArrayList<String>();
for(Map.Entry<String,String> map : hmap.entrySet()){
arList.add(map.getValue());
}
Create an ArrayList of String type to hold the values of the map. In its constructor call the method values() of the Map class.
Map <String, Object> map;
List<Object> list = new ArrayList<Object>(map.values());
Put i++ somewhere at the end of your loop.
In the above code, the 0 position of the array is overwritten because i is not incremented in each loop.
FYI: the below is doing a redundant search:
if(keys[i].equals(DATE)){
date_value[i] = map.get(keys[i]);
} else if(keys[i].equals(VALUE)){
value_values[i] = map.get(keys[i]);
}
replace with
if(keys[i].equals(DATE)){
date_value[i] = mapping.getValue();
} else if(keys[i].equals(VALUE)){
value_values[i] = mapping.getValue()
}
Another issue is that you are using i for date_value and value_values. This is not valid unless you intend to have null values in your array.
This is incredibly old, but I stumbled across it trying to find an answer to a different question.
my question is how do you get the values from both map keys in the arraylist?
for (String key : map.keyset()) {
list.add(key + "|" + map.get(key));
}
the Map size always return a value of 2, which is just the elements
I think you may be confused by the functionality of HashMap. HashMap only allows 1 to 1 relationships in the map.
For example if you have:
String TAG_FOO = "FOO";
String TAG_BAR = "BAR";
and attempt to do something like this:
ArrayList<String> bars = ArrayList<>("bar","Bar","bAr","baR");
HashMap<String,String> map = new HashMap<>();
for (String bar : bars) {
map.put(TAG_BAR, bar);
}
This code will end up setting the key entry "BAR" to be associated with the final item in the list bars.
In your example you seem to be confused that there are only two items, yet you only have two keys recorded which leads me to believe that you've simply overwritten the each key's field multiple times.
Suppose I have Hashmap with key datatype as KeyDataType
and value datatype as ValueDataType
HashMap<KeyDataType,ValueDataType> list;
Add all items you needed to it.
Now you can retrive all hashmap keys to a list by.
KeyDataType[] mKeys;
mKeys=list.keySet().toArray(new KeyDataType[list.size()]);
So, now you got your all keys in an array mkeys[]
you can now retrieve any value by calling
list.get(mkeys[position]);
Java 8 solution for produce string like "key1: value1,key2: value2"
private static String hashMapToString(HashMap<String, String> hashMap) {
return hashMap.keySet().stream()
.map((key) -> key + ": " + hashMap.get(key))
.collect(Collectors.joining(","));
}
and produce a list simple collect as list
private static List<String> hashMapToList(HashMap<String, String> hashMap) {
return hashMap.keySet().stream()
.map((key) -> key + ": " + hashMap.get(key))
.collect(Collectors.toList());
}
It has method to find all values from map:
Map<K, V> map=getMapObjectFromXyz();
Collection<V> vs= map.values();
Iterate over vs to do some operation
I have two hashmaps, in particular vocabs of two languages say english and german.I would like to concatenate both these map to return a single map.I tried :
hashmap.putall()
But, removed some of the entries which are common in both maps and replace it by single entry only.But i want to keep both the vocabs intact just concatenate those. Is there any method to do it? if not any other way to do. I would prefer any methods in hashmap.
[EDIT]
To make more clear, lets see two maps
at the 500 um die 500
0 1 2 0 1 2
resutls into
at the 500 um die 500
0 1 2 3 4 5
You'll have to write your own custom "putAll()` method then. Something like this would work:
HashMap<String> both = new HashMap<String>(english);
for(String key : german.keySet()) {
if(english.containsKey(key)) {
both.put(key, english.get(key)+german.get(key));
}
}
This first copies the English HashMap. Then puts in all the German words, concatenating if there is a duplicate key. You might want some kind of separator character like a / in between so you can later extract the two.
There isn't anything like that in the Java main library itself, you will have to use something provided by third parties like Google Guava's Multimap, it does exactly what you want, or build something like this manually.
You can download the Guava library at the project's website. Using a multimap is the same as using a map, as in:
Multimap<String,String> both = new ArrayListMultimap <String,String>();
both.putAll( german );
both.putAll( english);
for ( Entry<String,String> entry : both.entrySet() ) {
System.out.printf( "%s -> %s%n", entry.getKey(), entry.getValue() );
}
This code will print all key-value pairs including the ones that are present on both maps. So, if you have me->me at both german and english they would be printed twice.
You cannot do that directly with any Map implementation, since in a map, each key is unique.
A possible workaround is to use Map<Key, List<Value>>, and then do the concatenation of your maps manually. The advantage of using a List for the concatenated map, is that it will be easy to retrieve each of the individual values without any extra fiddling.
Something like that would work:
public Map<Key, List<Value>> concat(Map<Key, Value> first, Map<Key, Value> second){
Map<Key, List<Value>> concat = new HashMap<Key, List<Value>>();
putMulti(first, concat);
putMulti(second, concat);
return concat;
}
private void putMulti(Map<Key, Value> content, Map<Key, List<Value>> dest){
for(Map.Entry<Key, Value> entry : content){
List<Value> vals = dest.get(entry.getKey());
if(vals == null){
vals = new ArrayList<Value>();
dest.put(entry.getKey(), vals);
}
vals.add(entry.getValue());
}
}
Similar to #tskuzzy's answer
Map<String, String> both = new HashMap<String, String>();
both.putAll(german);
both.putAll(english);
for (String e : english.keySet())
if (german.containsKey(e))
both.put(e, english.get(e) + german.get(e));
Slight improvisation of #tskuzzy and #Peter's answer here. Just define your own StrangeHashMap by extending HashMap.
public class StrangeHashMap extends HashMap<String, String> {
#Override
public String put(String key, String value) {
if(this.containsKey(key)) {
return super.put(key, super.get(key) + value);
} else {
return super.put(key, value);
}
}
}
You can use it as so:
Map<String, String> map1 = new HashMap<String, String>();
map1.put("key1", "Value1");
map1.put("key2", "Value2");
Map<String, String> map2 = new HashMap<String, String>();
map2.put("key1", "Value2");
map2.put("key3", "Value3");
Map<String, String> all = new StrangeHashMap();
all.putAll(map1);
all.putAll(map2);
System.out.println(all);
The above prints the below for me:
{key3=Value3, key2=Value2, key1=Value1Value2}
Given the new elements in the question, it seems that what you actually need to use is lists. In this case, you can just do:
List<String> english = ...;
List<String> german = ...;
List<String> concat = new ArrayList<String>(english.size() + german.size());
concat.addAll(english);
concat.addAll(german);
And there you are. You can still use concat.get(n) to retreive the value nth value in the concatenated list.
I have a set of values which need to be shuffled when needed.
I don't know which variable type is best for me. Data is actually based on key-value structure.Like;
100 "white"
200 "black"
300 "red"
and like that. What I want to do is to change the key-value pairs according to I don't know yet, some algorithm.But they need to be shuffled like this, but shuffling need to be not random, so I can revert data when I need.
100 "red"
200 "white"
300 "black"
I don't really know how my approach should be to the solution. Should I use HashTable or something, and how can I shuffle them dynamically?
Any help is appreciated
Another way for shuffling the key-value mappings randomly:
public static <K,V> void shuffleMap(Map<K,V> map) {
List<V> valueList = new ArrayList<V>(map.values());
Collections.shuffle(valueList);
Iterator<V> valueIt = valueList.iterator();
for(Map.Entry<K,V> e : map.entrySet()) {
e.setValue(valueIt.next());
}
}
Edit:
If you don't want to change the original map (since you need it afterwards), you can create a new one instead:
public static <K,V> Map<K,V> shuffleMap(Map<K,V> map) {
List<V> valueList = new ArrayList<V>(map.values());
Collections.shuffle(valueList);
Iterator<V> valueIt = valueList.iterator();
Map<K,V> newMap = new HashMap<K,V>(map.size());
for(K key : map.keySet()) {
newMap.put(key, valueIt.next());
}
return newMap;
}
You do not really want a seemingly-randomly mixing which can be reverted (which quickly gets complicated), but simply retain your original map. If this does not fit, you need to describe your problem better.
Okay, you want to encrypt the mapping by using a secret key, giving another mapping, and then decrypt it again. Obviously random shuffling does not help here, and even pseudorandom is no good, since it gives no reliable way to reshuffle. In the basic case, your key would be a invertible map between the keys of our mapping.
public static <K,V> Map<K,V> encryptMap(Map<K,V> plainMap, Map<K,K> key) {
Map<K,V> cryptoMap = new HashMap<K,V>(plainMap.size());
for(Map.Entry<K,V> entry : plainMap.entrySet()) {
cryptoMap.put(key.get(entry.getKey()), entry.getValue());
}
return cryptoMap;
}
Decryption works the same, in fact, only using the reverse map of the key.
So, when you have your example keys of {100, 200, 300}, any permutation of these keys is a valid key for our "encryption scheme".
(There are only 6 possible ones, which is not very secure.)
Map sampleKey = new HashMap<Integer, Integer>();
sampleKey.put(100, 200);
sampleKey.put(200, 300);
sampleKey.put(300, 100);
Map sampleUnKey = new HashMap<Integer, Integer>();
for(Map.Entry<Integer, Integer> e : sampleKey) {
sampleUnKey.put(e.getValue(), e.getKey());
}
Map<Integer, String> data = new HashMap<Integer, String>();
data.put(100, "white");
data.put(200, "black");
data.put(300, "red");
System.out.println(data);
Map<Integer, String> encrypted = encryptMap(data, sampleKey);
System.out.println(encrypted);
Map<Integer, String> decrypted = encryptMap(data, sampleUnKey);
System.out.println(decrypted);
The map decrypted now should be the same as the original map.
For bigger keysets you would want to find a scheme to get a suitable
permutation of keys from some input-able key.
It looks like you need a list of tupples. A Map is exactly that. However, a standard like HashMap has no functionality for changing the relationship between key and value.
I think I would have implemented my own Map for this. Create a class that implements java.util.Map, implement the required methods and create some other methods for "mixing".
It all dependes on what functionality you really need on the list of tupples. Do you need to look up colors very fast? Can there be more than one tupple with the same numbers?
I am not sure how exactly you are going to shuffle the pairs, but if you need to shuffle them based on the key, you can use a Map:
Map<String, String> map = new HashMap<String, String>();
map.put("100", "white");
map.put("200", "black");
map.put("300", "red");
// swap 100 with 200
String temp = map.get("100");
map.put("100", map.get("200"));
map.put("200", temp);
Alternatively, if you need to shuffle the pair randomly, you can create a class Pair (which will basically store an int and a String), as suggested by larsmans, and store them in an array. Then, a slightly-modified version of Fisher-Yates shuffle can be used. Something along these lines:
// initialize list
List<Pair<Integer, String>> values = new ArrayList<Pair<Integer, String>>();
values.add(new Pair<Integer, String>(100, "white"));
values.add(new Pair<Integer, String>(200, "black"));
values.add(new Pair<Integer, String>(300, "red"));
// shuffle
System.out.println(values); // e.g., [100 white, 200 black, 300 red]
Random random = new Random();
for (int i = values.size() - 1; i > 1; i--) {
int j = random.nextInt(i + 1);
// swap values between i-th Pair and j-th Pair
Pair<Integer, String> iPair = values.get(i); // the iPair :-)
Pair<Integer, String> jPair = values.get(j);
String iString = iPair.getSecond();
iPair.setSecond(jPair.getSecond());
jPair.setSecond(iString);
}
System.out.println(values); // e.g., [100 red, 200 black, 300 white]