public class CollectionUtils {
public static <K, V> Map<K, V> createMap(Iterable<V> values, Function<V, K> keyFunction, boolean skipNullKeys) {
Map<K, V> map = new HashMap<>();
for (V value : values) {
K key = keyFunction.apply(value);
if (key != null || !skipNullKeys) {
map.put(key, value);
}
}
return map;
}
I would use small and simple data, e. g.
List<Integer> values = Arrays.asList(1, null);
Function<Integer, String> toKey = String::valueOf;
Map<String, Integer> withNull = createMap(values, toKey, false);
Map<String, Integer> noNull = createMap(values, toKey, true);
Then you can test with Map#size, Map#containsKey (needed for null-key) and ...get("1").equals(1).
But as I mentioned in the comment, if your function may result in the same key for different values you only have the last value, e. g. Function<Integer, Integer> toKey = i -> i%2 will only procude 0 or 1 as a key (and a NullPointerException for null-values) so List<Integer> values = Arrays.asList(1, 3) will produce a Map with only one entry "1" -> 3.
Related
i want get result like { "key1" : 4 ,"key2" :2 }
i known i can use map and groupby and such as
list.stream()
.map(map -> map2Entity(map))
.collect(Collectors.groupingBy(Entity::getKey,Collectors.summarizingInt(Entity::getCnt)) )
This is my code and how implements (todo) code
public void test() {
List<Map<String, Object>> list = Arrays.asList(
createNewMap("key1", 1),
createNewMap("key2", 2),
createNewMap("key1", 3)
);
// i want get result like {"key1":4,"key2":2}
// how can i get the result don't use map()
list.stream()
.collect(Collectors.groupingBy(this::getKey),....(todo));
}
private String getKey(Map<String,Object> map){
return (String) map.get("key");
}
private Map<String, Object> createNewMap(String key, Integer val) {
Map<String, Object> map = new HashMap<>();
map.put("key", key);
map.put(key, val);
return map;
}
You have to use the flatMap operator along with the groupingBy collector. Here's how it looks.
Map<String, Integer> keyToSumValuesMap = list.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.summingInt(Map.Entry::getValue)));
Moreover do not use Object type to represent integers since that is not type safe. Consider declaring method level generics to overcome that issue. Here's how it looks.
private static <S, T> Map<S, T> createNewMap(S key, T val) {
Map<S, T> map = new HashMap<>();
map.put(key, val);
return map;
}
And the output now looks like this:
{key1=4, key2=2}
What is the best way to obtain from a Map a new List with all map values??
Is this correct?
List<Value> listValues = new ArrayList<>();
for(TypeKey keys : map.keySet()){
for(TypeValue values : map.get(keys)){
listValues.add(values);
}
}
If you have a Map<Key, Value>, the Map#values() method will give you a Collection<Value>.
For a Map<Key, List<Value>>, the values() method will - obviously- give you a Collection<List<Value>> that can be flattend:
List<Value> values = map.values().stream()
.flatMap(List::stream)
.collect(Collectors.toList());
If you can not use the Java 8 Stream API, you can still make your code a bit shorter by using Map#values to iterate the values lists directly, instead of the keys, and List#addAll to add all the values to the result list at once.
public <K, V> List<V> flatValues(Map<K, List<V>> map) {
List<V> result = new ArrayList<>();
for (List<V> values : map.values()) {
result.addAll(values);
}
return result;
}
public <K, V> List<V> flatValues(Map<K, List<V>> map) {
List<V> result = new ArrayList<>();
for (List<V> values : map.values()) {
result.addAll(values);
}
return result;
}
public <K, V> List<V> flatValues(Map<K, List<V>> map) {
List<V> result = new ArrayList<>();
for (List<V> values : map.values()) {
result.addAll(values);
}
return result;
}
i have used java stream
I would like to find the biggest number in HashSet and HashMap. Say I have the number [22,6763,32,42,33] in my HashSet and I want to find the largest number in my current HashSet..how would i do this? and Same thing for the HashMap as well. I hope you can help me with it. Thank you.
You can use Collections.max(Collection) to find the maximum element out of any collection.
Similarly, for a HashMap, you can use the same method on its keySet() or values(), depending upon whether you want maximum key, or maximum value.
Also, if you want as such, you can use a TreeSet and TreeMap instead, that stores the elements in sorted key order.
try
int max = Collections.max(set);
int maxKey = Collections.max(map.keySet());
int maxValue Collections.max(map.values());
If you are forced to use a HashSet/HashMap, then you have to scan the whole HashSet/HashMap in order to find the maximum. Library functions like Collections.max() will do like this.
If you want O(1) retrieval of the maximum, and you are allowed to change the type of collection being used, use a sorted set/map (e.g. TreeSet/TreeMap).
Something like this:
Set<Integer> values = new HashSet<Integer>() {{
add(22);
add(6763);
add(32);
add(42);
add(33);
}};
int maxValue = Integer.MIN_VALUE;
for (int value : values) {
if (value > maxValue) {
maxValue = value;
}
}
And this:
Map<String, Integer> values = new HashMap<String, Integer>() {{
put("0", 22);
put("1", 6763);
put("2", 32);
put("3", 42);
put("4", 33);
}};
int maxValue = Integer.MIN_VALUE;
for (int value : values.values()) {
if (value > maxValue) {
maxValue = value;
}
}
In case of TreeMap, if you know the key/values are inserted randomly, the tree will be more or less balanced. Trees become unbalanced, if data is inserted in already sorted order, the capability to quickly find (or insert or delete) a given element is lost. In case of unbalanced tree, it will take time proportional to n, O(n) else O(1).
Consider using Apache Commons Math. Here is the API docs.
The class of interest is SummaryStatistics. It works with doubles and computes max, min, mean etc. on the fly (as you add values to it). The data values are not stored in memory, so this class can be used to compute statistics for very large data streams.
Here is a simple method which does what you are asking:
public String getMapKeyWithHighestValue(HashMap<String, Integer> map) {
String keyWithHighestVal = "";
// getting the maximum value in the Hashmap
int maxValueInMap = (Collections.max(map.values()));
//iterate through the map to get the key that corresponds to the maximum value in the Hashmap
for (Map.Entry<String, Integer> entry : map.entrySet()) { // Iterate through hashmap
if (entry.getValue() == maxValueInMap) {
keyWithHighestVal = entry.getKey(); // this is the key which has the max value
}
}
return keyWithHighestVal;
}
Note : If you want to find the biggest value from Map try maxEntry.get().getValue() instead of maxEntry.get().getKey()
1. Using Stream
public <K, V extends Comparable<V>> V maxUsingStreamAndLambda(Map<K, V> map) {
Optional<Entry<K, V>> maxEntry = map.entrySet()
.stream()
.max((Entry<K, V> e1, Entry<K, V> e2) -> e1.getValue()
.compareTo(e2.getValue())
);
return maxEntry.get().getKey();
}
2. Using Collections.max() with a Lambda Expression
public <K, V extends Comparable<V>> V maxUsingCollectionsMaxAndLambda(Map<K, V> map) {
Entry<K, V> maxEntry = Collections.max(map.entrySet(), (Entry<K, V> e1, Entry<K, V> e2) -> e1.getValue()
.compareTo(e2.getValue()));
return maxEntry.getKey();
}
3. Using Stream with Method Reference
public <K, V extends Comparable<V>> V maxUsingStreamAndMethodReference(Map<K, V> map) {
Optional<Entry<K, V>> maxEntry = map.entrySet()
.stream()
.max(Comparator.comparing(Map.Entry::getValue));
return maxEntry.get()
.getKey();
}
4. Using Collections.max()
public <K, V extends Comparable<V>> V maxUsingCollectionsMax(Map<K, V> map) {
Entry<K, V> maxEntry = Collections.max(map.entrySet(), new Comparator<Entry<K, V>>() {
public int compare(Entry<K, V> e1, Entry<K, V> e2) {
return e1.getValue()
.compareTo(e2.getValue());
}
});
return maxEntry.getKey();
}
5. Using Simple Iteration
public <K, V extends Comparable<V>> V maxUsingIteration(Map<K, V> map) {
Map.Entry<K, V> maxEntry = null;
for (Map.Entry<K, V> entry : map.entrySet()) {
if (maxEntry == null || entry.getValue()
.compareTo(maxEntry.getValue()) > 0) {
maxEntry = entry;
}
}
return maxEntry.getKey();
}
I'm stuck on how to transfer key-value pairs from map1 into map2 only if each key has a unique value in map1.
Let's say I have the following maps:
map1: [1,2] [2,4] [4,4]
map2: [1,2] [2,4]
I suppose the algorithm would be:
Loop through entries in the first map.
Add a key to map2.
Add a value to a set which checks against the values of map2
If the values are duplicate the value doesn't get added to the set and disregard adding its corresponding key to map2.
Code snippet:
public static <K,V> Map<K,V> unique (Map<K,V> m) {
Map<K,V> newMap = new ArrayMap<K,V>();
//Remember all values in the newMap.
Set<V> holding = new ArraySet<V>(newMap.values());
for (Map.Entry<K, V> graphEntry : m.entries()) {
//not sure.
}
return newMap;
}
Is my idea of how its supposed to be done on the right track? Quite lost here.
From a Map<K, V> create a Map<V, K> that will add the item if and only if the key is not in the map. Using this Map<V, K>, recreate your Map<K, V>.
public static <K, V> Map<K, V> createMap(Map<K, V> m) {
Map<K, V> map = new HashMap<K, V>();
Map<V, K> tmpMap = new HashMap<V, K>();
for(Map.Entry<K, V> entry : m.entrySet()) {
if (!tmpMap.containsKey(entry.getValue())) {
tmpMap.put(entry.getValue(), entry.getKey());
}
}
for(Map.Entry<V, K> entry : tmpMap.entrySet()) {
map.put(entry.getValue(), entry.getKey());
}
return map;
}
If you need to keep the preserver order of the data, use LinkedHashMap instead of HashMap.
Check out Guava BiMap.. This is what you need..
Although your problem is solved, you can take a look at the below code, to use Guava API for what you want to do: -
public void removeDuplicateValue() {
Map<Integer, String> existingMap = new HashMap<Integer, String>();
existingMap.put(1, "a");
existingMap.put(2, "b");
// Create a new BiMap
BiMap<Integer, String> biMap = HashBiMap.create();
for (Integer val: existingMap.keySet()) {
// forcePut will add a key-value pair, and overwrite the duplicate value.
biMap.forcePut(val, existingMap.get(val));
}
// Create Inverse Map for newly created BiMap.
BiMap<String, Integer> inverseBiMap = biMap.inverse();
for(String val: inverseBiMap.keySet()) {
System.out.println(val + ":" + biMap.get(val));
}
}
Try this one..
Map<String, String> myMap1 = new TreeMap<String, String>();
myMap1.put("1", "One");
myMap1.put("2", "Two");
myMap1.put("3", "One");
myMap1.put("4", "Three");
myMap1.put("5", "Two");
myMap1.put("6", "Three");
Set<String> mySet = new HashSet<String>();
for (Iterator itr = myMap1.entrySet().iterator(); itr.hasNext();)
{
Map.Entry<String, String> entrySet = (Map.Entry) itr.next();
String value = entrySet.getValue();
if (!mySet.add(value))
{
itr.remove();
}
}
Map<String, String> myMap2 = new TreeMap<String, String>(myMap1);
System.out.println("Result :"+myMap2);
Result :{1=One, 2=Two, 4=Three}
I need to write a small snippet of code where I need to check contents of a map (key value) if it exists in another map , remove it from the map
E.g
Map1:
1=>obj1
2=>obj21
3=>obj3
4=>obj4
Other map
Map2:
10=>obj10
20=>obj20
2=>obj2
30=>obj30
3=>obj3
The result of fun (Map1, Map2)
after it executes it has the following ouput
Map2:
10=>obj10
2=>obj2
20=>obj20
30=>obj30
Is iterating over the smaller map and checking contents (key, value) is iterating over the smaller map and checking the key and contents in the bigger map the most efficient way to go about it.
m1.entrySet().removeAll(m2.entrySet());
where m1 is the Map to be modified, and m2 is the map with the mappings that need to be removed from m1.
private static <K, V> void fun(Map<K, V> a, Map<K, V> b) {
Map<K, V> shortestMap = a.size() < b.size() ? a : b;
Map<K, V> longestMap = a.size() > b.size() ? a : b;
Set<Entry<K, V>> shortestMapEntries = shortestMap.entrySet();
Set<Entry<K, V>> longestMapEntries = longestMap.entrySet();
longestMapEntries.removeAll(shortestMapEntries);
}
See java.util.Collection
boolean removeAll(Collection<?> c)
private static <K, V> removeDuplicates(Map<K, V> map1, Map<K, V> map2) {
for (K key : map1.keySet()) {
V val1 = map1.get(key);
V val2 = map2.get(key);
if (val2 != null && val2.equals(val1)
map2.remove(key);
}
}