So I have two maps. First one (idsandcount) has the id as key and number ordered as count. Second map has id as key and ingredient as value. How do implement a method that gives a list with an arraylist?
public static List<Ingredient> ingredientsFromIdAndCount(Map<Long, Integer> idsAndCount, Map<Long, Ingredient> articles) {
Map<Ingredient, Long> inversedArt = new HashMap<>();
articles.forEach((key, value) -> inversedArt.put((value), key));
List<Ingredient> ingredientList = new ArrayList<>();
for (Ingredient art : articles.values()) ingredientList.add(art);
return ingredientList;
From Test class:
#Test
#DisplayName("should get the ingredients from the passed menu in the stated quantities of the input map")
void ingredientsFromIdAndCount() {
Map<Long, Integer> counts = Map.of(
66L, 1,
17L, 2);
private final Map<Long, Ingredient> testMenu = Map.of(
42L, gurken,
66L, kaese,
17L, fleisch);
List<Ingredient> expected = List.of(kaese, fleisch, fleisch);
List<Ingredient> actual =
MenuUtils.ingredientsFromIdAndCount(counts, testMenu);
I basically want an arraylist of kaese, fleisch, fleisch.
I have tried inversing(don't know if i need it here). My main thought was to get an arraylist of the ids from the first map. An arraylist of 66, 17, 17 to then get the values from the second map using these key. Problem is I just started working with maps and arraylists, so its very confusing at the moment.
public static void main(String[] args) {
/* We will be able to modify the values in this map */
Map<Long, Integer> counts = new HashMap<>();
counts.put(66L, 1);
counts.put(17L, 2);
/* You cannot modify keys/value of map if it is implemented with Map.of() */
Map<Long, String> testMenu = Map.of(
42L, "gurken",
66L, "kaese",
17L, "fleisch");
System.out.println("Count Map: " + counts);
System.out.println("Ingredient Map: " + testMenu + "\n");
List<String> ingredients = new ArrayList<>();
/* Access both key/value with entrySet() */
for(Map.Entry<Long, Integer> entry : counts.entrySet()) {
long key = entry.getKey();
int val = entry.getValue();
for(int i = 0; i < val; i++) {
ingredients.add(testMenu.get(key));
}
counts.put(key, counts.get(key) - val);
}
System.out.println("List of ingredients: " + ingredients);
System.out.println("Updated Count Map: " + counts);
}
This is the output:
Count Map: {17=2, 66=1}
Ingredient Map: {17=fleisch, 66=kaese, 42=gurken}
List of ingredients: [fleisch, fleisch, kaese]
Updated Count Map: {17=0, 66=0}
Note, keys and values are immutable when you use the Map.of() method.
I used strings instead of your Ingredients class object in the map, but you can modify the code with a little tinkering. If your having an issue, let me know.
Related
I have created an ArrayList of HashMaps and I know how to get all keys and values of all HashMaps in the list, but then I decided to make it complicated and iterate through the ArrayList and get only specific HashMap values(based on keys). I have no idea how to do that.
How can I modify printArrayList method to get only idand sku values from all hashmaps?
Right now I have the following example:
public class HashmapArraylist {
public static void main(String[] args) throws Exception {
Map<String, Object> map1 = new HashMap<>();
map1.put("id", 1);
map1.put("sku", "test1");
map1.put("quantity", 1);
Map<String, Object> map2 = new HashMap<>();
map2.put("id", 2);
map2.put("sku", "test2");
map2.put("quantity", 2);
Map<String, Object> map3 = new HashMap<>();
map3.put("id", 3);
map3.put("sku", "test3");
map3.put("quantity", 3);
ArrayList<Map<String, Object>> arrayList = new ArrayList<>();
arrayList.add(map1);
arrayList.add(map2);
arrayList.add(map3);
printArrayList(arrayList);
}
public static void printArrayList(ArrayList<Map<String, Object>> arrayList) {
for (Map<String, Object> entry : arrayList) {
for (String key : entry.keySet()) {
String value = entry.get(key).toString();
System.out.println(key + " : " + value);
}
System.out.println("-----------");
}
}
}
Your iterator for the arrayList is correct. To retrieve a value from a map, simply provide the key into the 'get' function of the entry. Since your map has a "String" key to an "Object" value, you can use "toString()" on it to get the string from the Object returned from your key.
public static void printArrayList(ArrayList<Map<String, Object>> arrayList) {
for (Map<String, Object> entry : arrayList) {
String myID = entry.get("id").toString();
String mySKU = entry.get("sku").toString();
System.out.print("id:" + myID + " sku: " + mySKU);
System.out.println("-------------------");
}
}
user681574 seems to have already answered your problem, but I will just add one Java8 example code to do the same thing as you need, using streams
public static void printArrayList(ArrayList<Map<String, Object>> arrayList) {
arrayList.stream() //stream out of arraylist
.forEach(map -> map.entrySet().stream() //iterate through each map in the list, create stream out of maps' entryset
.filter(entry -> entry.getKey().equals("id") || entry.getKey().equals("sku")) //filter out only entries that we need (where key is "id" or "sku")
.forEach(idOrSku -> System.out.println(idOrSku.getKey() + ":" + idOrSku.getValue()))); //Iterate through the id/sku entries and print them out just as we want to
}
Name - Code (String)
A - 123
B - 123
C - 23
D - 123
E - 23
F - 23
G - 66
H - 66
What's the best data structure to represent this data. Names should be able to iterate easily.
Edit
Names are unique.
What's needed to be done is something like this.
Had doubts in using Hashmap that why I asked.
Code is a STRING
for( loop dataStructure names (lets say n)){
if(NAME.equals(n){
String code = dataStructure.get(n);
do somthing
}
}
If the names are unique, a HashMap woulrd be apropriate.
You can iterate over the keys with keys().
To iterate over the entries you can iterate over the entrySet().
See the JavaDoc of Map
If you need to perform a reverse lookup you could use the BiMap from Guava. (General a very good library)
Map entries example:
public final class MapExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("A", "123");
for (Map.Entry<String, String> mapEntry : map.entrySet()) {
if (mapEntry.getKey().equals("A")) {
final String code = mapEntry.getValue();
System.out.println("Your desired code: " + code);
}
}
}
}
But since NAME seems to be a constant, you could simple do String code = map.get(NAME)?
I thinks you are considering this:
public enum Code {
A("123"),
B("123"),
C("23"),
D("123"),
E("23"),
F("23"),
G("66"),
H("66");
final public String value;
Code(String value) {
this.value = value;
}
}
String h = Code.H.value;
for (Code code : Code.values()) {
System.out.printf("Name %s, code %s%n", code, code.value);
}
Sounds like a Map. Specifically, if the order of the names is important, you can use a TreeMap.
You can populate it with the put method, and then iterate over the entries (or just the keys, or just the values):
// Fill the map:
Map<String, String> map = new TreeMap<>();
map.put("A", "123");
map.put("B", "123");
// etc...
// Iterate over it:
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.pritnln ("Key: " + entry.getKey() + " value: " + entry.getValue());
}
EDIT:
If the order is not important, as noted in later edits to the OP, a HashMap would do just fine.
Note, however, that if you're looking for a specific key, like stated in the example in the OP, there's no point in looping over the keys - you just need to use get or containsKey:
String name = ...;
String code = map.get(name);
if (code != null) {
// do something...
}
I would suggest go for HashMap
The HashMap class uses a hashtable to implement the Map interface.
This allows the execution time of basic operations, such as get( )
and put( ), to remain constant even for large sets
HashMap are efficient for locating a value based on a key and
inserting and deleting values based on a key. The entries of a
HashMap are not ordered.
import java.util.HashMap;
import java.util.Set;
public class MyHashMapRead {
public static void main(String a[]){
HashMap<String, Integer> hm = new HashMap<String, Integer>();
//add key-value pair to hashmap
hm.put("A", "1");
hm.put("B", "2");
hm.put("C","3");
System.out.println(hm);
Set<String> keys = hm.keySet();
for(String key: keys){
System.out.println("Value of "+key+" is: "+hm.get(key));
}
}
}
I have an homework to do, so I have finished the script but the problem is with the values.
The main code is (I cannot change it due to homework) :
List<String> result = cw.getResult();
for (String wordRes : result) {
System.out.println(wordRes);
}
It have to return:
abc 2
def 2
ghi 1
I have no idea how to handle that.
Now only shows:
abc
def
ghi
I have no idea how to change this method getResult to return with the value of the hashmap as well without changing the first main code.
public List<String> getResult() {
List<String> keyList = new ArrayList<String>(list.keySet());
return keyList;
}
The hashmap is: {abc=2, def=2, ghi=1}
And list: Map<String, Integer> list = new HashMap<String, Integer>();
Please help me if you know any resolution.
I think that now that you have learned about keySet and valueSet, your next task is to learn about entrySet. That's a collection of Map.Entry<K,V> items, which are in turn composed of the key and the value.
That's precisely what you need to complete your task - simply iterate over the entrySet of your Map while adding a concatenation of the value and the key to your result list:
result.add(entry.getKey() + " " + entry.getValue());
Note that if you use a regular HashMap, the items in the result would not be arranged in any particular order.
You need to change this line:
List<String> keyList = new ArrayList<String>(list.keySet());
to:
//first create the new List
List<String> keyList = new List<String>();
//iterate through the map and insert the key + ' ' + value as text
foreach(string item in list.keySet())
{
keyList.add(item+' '+list[item]);
}
return keyList;
I haven't written java in a while so compiler errors might appear, but the idea should work
Well simplest way make an ArrayList and add as #dasblinkenlight said...
Iterator<?> it = list.entrySet().iterator();
while (it.hasNext()) {
#SuppressWarnings("rawtypes")
Map.Entry maps = (Map.Entry) it.next();
lista.add(maps.getKey() + " " + maps.getValue());
}
}
public List<String> getResult() {
List<String> temp = lista;
return temp;
}
If you want to iterate over map entries in order of keys, use an ordered map:
Map<String, Integer> map = new TreeMap<String, Integer>();
Then add your entries, and to print:
for (Map.Entry<String, Ibteger> entry : map.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
I want to retrieve k,v-pairs from a HashMap.
The entrys are like this:
a = 3,4
b = 5,6
and so on. I need combinations of these values.
a=3, b=5
a=3, b=6
a=4, b=5
a=4, b=6
I don't know how many keys and how many entrys the values have. With entrySet I can get the values but not combinations. It looks like recursion but how?
Here's my code:
HashMap<String, String[]> map = new HashMap<String, String[]>();
BufferedReader file = new BufferedReader(new FileReader("test.txt"));
String str;
while ((str = file.readLine()) != null) {
// ... logic
map.put(key, value);
}
System.out.println("number of keys: " + map.size());
for (Map.Entry<String, String[]> entry : map.entrySet()) {
for (String value : entry.getValue()) {
System.out.println(entry.getKey() + ": " + value);
}
}
file.close();
You can try the following code:
public void mapPermute(Map<String, String[]> map, String currentPermutation) {
String key = map.keySet().iterator().next(); // get the topmost key
// base case
if (map.size() == 1) {
for (String value : map.get(key)) {
System.out.println(currentPermutation + key + "=" + value);
}
} else {
// recursive case
Map<String, String[]> subMap = new HashMap<String, String[]>(map);
for (String value : subMap.remove(key)) {
mapPermute(subMap, currentPermutation + key + "=" + value + ", ");
}
}
}
No guarantees on memory efficiency or speed. If you want to preserve the order of the keys in the map, you will have to pass in a TreeMap and change the code to use a TreeMap under the recursive case.
As the base case suggests, I'm assuming you have at least one entry in your map.
You can obtain a Cartesian product of map key-value combinations using a map and reduce approach.
Try it online!
Map<String, String[]> map = Map.of(
"a", new String[]{"3", "4"},
"b", new String[]{"5", "6"});
List<Map<String, String>> comb = map.entrySet().stream()
// Stream<List<Map<String,String>>>
.map(e -> Arrays.stream(e.getValue())
.map(v -> Map.of(e.getKey(), v))
.collect(Collectors.toList()))
// summation of pairs of list into a single list
.reduce((list1, list2) -> list1.stream()
// combinations of inner maps
.flatMap(map1 -> list2.stream()
// concatenate into a single map
.map(map2 -> {
Map<String, String> m = new HashMap<>();
m.putAll(map1);
m.putAll(map2);
return m;
}))
// list of combinations
.collect(Collectors.toList()))
// otherwise, an empty list
.orElse(Collections.emptyList());
// output, order may vary
comb.forEach(System.out::println);
Output, order may vary:
{a=3, b=5}
{a=3, b=6}
{a=4, b=5}
{a=4, b=6}
See also: Cartesian product of map values
It looks to me like you really want a MultiMap. In particular, ArrayListMultimap allows duplicate entries:
ArrayListMultimap<String, String> map = ArrayListMultimap.create();
for each line in file:
parse key k
for each value in line:
parse value v
map.put(k, v);
for (Map.Entry<String, String> entry : map.entries()) {
String key = entry.getKey();
String value = entry.getValue();
}
If you want a cartesian product of maps, you could compute that directly using recursion, or you could iterate over the maps: create a list of iterators and iterate odometer-style; when iterator N reaches its end, advance iterator N+1 and reset iterators 1..N.
Just poked around and found this SO question.
So I'd recommend you use guava's Sets.cartesianProduct for the cartesian product. Here's my poking around code, which you could adapt to your input logic:
String key1 = "a";
Set<Integer> values1 = Sets.newLinkedHashSet(Arrays.asList(1, 2, 3, 4));
String key2 = "b";
Set<Integer> values2 = Sets.newLinkedHashSet(Arrays.asList(5, 6, 7));
String key3 = "c";
Set<Integer> values3 = Sets.newLinkedHashSet(Arrays.asList(8, 9));
List<String> keys = Arrays.asList(key1, key2, key3);
Set<List<Integer>> product = Sets.cartesianProduct(values1, values2, values3);
for (List<Integer> values : product) {
for (int i = 0; i < keys.size(); ++i) {
String key = keys.get(i);
int value = values.get(i);
System.out.print(key + "=" + value + "; ");
}
System.out.println();
}
How to move a particular HashMap entry to Last position?
For Example, I have HashMap values like this:
HashMap<String,Integer> map = new HashMap<String,Integer>();
map= {Not-Specified 1, test 2, testtest 3};
"Not-Specified" may come in any position. it may come first or in the middle of the map. But i want to move the "Not-Specified" to the last position.
How can I do that?
To answer your question in one sentence:
Per default, Maps don't have a last entry, it's not part of their contract.
And a side note: it's good practice to code against interfaces, not the implementation classes (see Effective Java by Joshua Bloch, Chapter 8, Item 52: Refer to objects by their interfaces).
So your declaration should read:
Map<String,Integer> map = new HashMap<String,Integer>();
(All maps share a common contract, so the client need not know what kind of map it is, unless he specifies a sub interface with an extended contract).
Possible Solutions
Sorted Maps:
There is a sub interface SortedMap that extends the map interface with order-based lookup methods and it has a sub interface NavigableMap that extends it even further. The standard implementation of this interface, TreeMap, allows you to sort entries either by natural ordering (if they implement the Comparable interface) or by a supplied Comparator.
You can access the last entry through the lastEntry method:
NavigableMap<String,Integer> map = new TreeMap<String, Integer>();
// add some entries
Entry<String, Integer> lastEntry = map.lastEntry();
Linked maps:
There is also the special case of LinkedHashMap, a HashMap implementation that stores the order in which keys are inserted. There is however no interface to back up this functionality, nor is there a direct way to access the last key. You can only do it through tricks such as using a List in between:
Map<String,String> map = new LinkedHashMap<String, Integer>();
// add some entries
List<Entry<String,Integer>> entryList =
new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Entry<String, Integer> lastEntry =
entryList.get(entryList.size()-1);
Proper Solution:
Since you don't control the insertion order, you should go with the NavigableMap interface, i.e. you would write a comparator that positions the Not-Specified entry last.
Here is an example:
final NavigableMap<String,Integer> map =
new TreeMap<String, Integer>(new Comparator<String>() {
public int compare(final String o1, final String o2) {
int result;
if("Not-Specified".equals(o1)) {
result=1;
} else if("Not-Specified".equals(o2)) {
result=-1;
} else {
result =o1.compareTo(o2);
}
return result;
}
});
map.put("test", Integer.valueOf(2));
map.put("Not-Specified", Integer.valueOf(1));
map.put("testtest", Integer.valueOf(3));
final Entry<String, Integer> lastEntry = map.lastEntry();
System.out.println("Last key: "+lastEntry.getKey()
+ ", last value: "+lastEntry.getValue());
Output:
Last key: Not-Specified, last value: 1
Solution using HashMap:
If you must rely on HashMaps, there is still a solution, using a) a modified version of the above comparator, b) a List initialized with the Map's entrySet and c) the Collections.sort() helper method:
final Map<String, Integer> map = new HashMap<String, Integer>();
map.put("test", Integer.valueOf(2));
map.put("Not-Specified", Integer.valueOf(1));
map.put("testtest", Integer.valueOf(3));
final List<Entry<String, Integer>> entries =
new ArrayList<Entry<String, Integer>>(map.entrySet());
Collections.sort(entries, new Comparator<Entry<String, Integer>>(){
public int compareKeys(final String o1, final String o2){
int result;
if("Not-Specified".equals(o1)){
result = 1;
} else if("Not-Specified".equals(o2)){
result = -1;
} else{
result = o1.compareTo(o2);
}
return result;
}
#Override
public int compare(final Entry<String, Integer> o1,
final Entry<String, Integer> o2){
return this.compareKeys(o1.getKey(), o2.getKey());
}
});
final Entry<String, Integer> lastEntry =
entries.get(entries.size() - 1);
System.out.println("Last key: " + lastEntry.getKey() + ", last value: "
+ lastEntry.getValue());
}
Output:
Last key: Not-Specified, last value: 1
HashMap doesn't have "the last position", as it is not sorted.
You may use other Map which implements java.util.SortedMap, most popular one is TreeMap.
A SortedMap is the logical/best choice, however another option is to use a LinkedHashMap which maintains two order modes, most-recently-added goes last, and most-recently-accessed goes last. See the Javadocs for more details.
When using numbers as the key, I suppose you could also try this:
Map<Long, String> map = new HashMap<>();
map.put(4L, "The First");
map.put(6L, "The Second");
map.put(11L, "The Last");
long lastKey = 0;
//you entered Map<Long, String> entry
for (Map.Entry<Long, String> entry : map.entrySet()) {
lastKey = entry.getKey();
}
System.out.println(lastKey); // 11
move does not make sense for a hashmap since its a dictionary with a hashcode for bucketing based on key and then a linked list for colliding hashcodes resolved via equals.
Use a TreeMap for sorted maps and then pass in a custom comparator.
In such scenario last used key is usually known so it can be used for accessing last value (inserted with the one):
class PostIndexData {
String _office_name;
Boolean _isGov;
public PostIndexData(String name, Boolean gov) {
_office_name = name;
_isGov = gov;
}
}
//-----------------------
class KgpData {
String _postIndex;
PostIndexData _postIndexData;
public KgpData(String postIndex, PostIndexData postIndexData) {
_postIndex = postIndex;
_postIndexData = postIndexData;;
}
}
public class Office2ASMPro {
private HashMap<String,PostIndexData> _postIndexMap = new HashMap<>();
private HashMap<String,KgpData> _kgpMap = new HashMap<>();
...
private void addOffice(String kgp, String postIndex, String officeName, Boolean gov) {
if (_postIndexMap.get(postIndex) == null) {
_postIndexMap.put(postIndex, new PostIndexData(officeName, gov));
}
_kgpMap.put( kgp, new KgpData(postIndex, _postIndexMap.get(postIndex)) );
}
Find missing all elements from array
int[] array = {3,5,7,8,2,1,32,5,7,9,30,5};
TreeMap<Integer, Integer> map = new TreeMap<>();
for(int i=0;i<array.length;i++) {
map.put(array[i], 1);
}
int maxSize = map.lastKey();
for(int j=0;j<maxSize;j++) {
if(null == map.get(j))
System.out.println("Missing `enter code here`No:"+j);
}