Adding to hashmap and arraylist - java

I am trying to add hashmaps to array list.
But the map(completeEntrie) is overriding the previous values when I am trying to add more than one value to arraylist(listOfCompleteEntries)
public class MapExample {
public static void main(String a[]) {
ArrayList listOfCompleteEntries = new ArrayList();
Map<String, String> completeEntrie = new HashMap<String, String>();
for (int i = 0; i < 3; i++) {
completeEntrie.put("KEY_NAME", "Number:" + i);
System.out.print(completeEntrie.toString());
listOfCompleteEntries.add(completeEntrie);
System.out.println(listOfCompleteEntries.toString());
}
System.out.println(listOfCompleteEntries.toString());
}
}
Output for the above code is
{KEY_NAME=Number:0}[{KEY_NAME=Number:0}]
{KEY_NAME=Number:1}[{KEY_NAME=Number:1}, {KEY_NAME=Number:1}]
{KEY_NAME=Number:2}[{KEY_NAME=Number:2}, {KEY_NAME=Number:2}, {KEY_NAME=Number:2}]
[{KEY_NAME=Number:2}, {KEY_NAME=Number:2}, {KEY_NAME=Number:2}]
But i want the output to be like this
{KEY_NAME=Number:0}[{KEY_NAME=Number:0}]
{KEY_NAME=Number:1}[{KEY_NAME=Number:0}, {KEY_NAME=Number:1}]
{KEY_NAME=Number:2}[{KEY_NAME=Number:0}, {KEY_NAME=Number:1}, {KEY_NAME=Number:2}]
[{KEY_NAME=Number:0}, {KEY_NAME=Number:1}, {KEY_NAME=Number:2}]
Also please explain why is this map overriding the previous map in arraylist.
Thanks for your help.

Despite the irrelevant title, you need to construct a new map instance for each unique entry you want to add to the array list. Without this, you are modifying the same map instance.

Related

How to create a HashMap that would have String as key and the value would be another HashMap from one list of custom object?

I have a list of custom object,
public class Assignmentsdata {
String assignmentId;
String teacherId;
String groupName;
String sectionId;
String levelId;
String startTime;
}
ArrayList<Assignmentsdata> list = new ArrayList<>();
lets say there are 20 elements in that list.
Now I want to get the output which is a hashmap of startTime as a key and the Value would be a new HashMap of GroupID and a list of Assignments of those that had the same groupName.
OutPut Example
HashMap<startTime,HasMap<groupName,List> hashMap = new HashMap();
a little more insight about the problem: First I want to categorise based on startTime(Month) then i want to categorise based on groupName, Thanks in advance.
I have successfully categorised based on group name and created a map through below code:
for( int i = 0; i<assignmentsdataArrayList.size();i++ ){
if (hashMap.size()>0){
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}else {
hashMap.put(assignmentsdataArrayList.get(i).getGroupName(),new ArrayList<Assignmentsdata>());
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
}
After that I am lost on how to categorise this hashmap based on the startDate and create a hashmap that would look like the above hashmap in the output heading.
your code may throw a NullPointerException at the first if branch
if (hashMap.size()>0)
{hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
the map.size()>0 doesnt means the Value of GroupName has put a new ArrayList already.
the anwser of using loop should like this
Map<String, Map<String, List<Assignmentsdata>>> map = new HashMap<>();
for (Assignmentsdata assignmentsdata : list) {
if (!map.containsKey(assignmentsdata.getStartTime())) {
map.put(assignmentsdata.getStartTime(), new HashMap<>());
}
Map<String, List<Assignmentsdata>> startTimeMap = map.get(assignmentsdata.startTime);
if (!startTimeMap.containsKey(assignmentsdata.getGroupName())) {
startTimeMap.put(assignmentsdata.getGroupName(), new ArrayList<>());
}
startTimeMap.get(assignmentsdata.groupName).add(assignmentsdata);
}
or you could use the java stream().collect(Collectors.groupingBy()) api to get the result easily
Map<String, Map<String, List<Assignmentsdata>>> result = list.stream()
.collect(Collectors.groupingBy(Assignmentsdata::getStartTime,Collectors.groupingBy(Assignmentsdata::getGroupName)));
I am answering my own question as I solved it if anyone has a better answer please passed your answer aswell, ill accept another answer suitable and efficient answer.
for( int i = 0; i<assignmentsdataArrayList.size();i++ ){
if (hashMap.size()>0){
if (hashMap.get(assignmentsdataArrayList.get(i).getGroupName())==null){
hashMap.put(assignmentsdataArrayList.get(i).getGroupName(),new ArrayList<Assignmentsdata>());
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}else{
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
}else {
hashMap.put(assignmentsdataArrayList.get(i).getGroupName(),new ArrayList<Assignmentsdata>());
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
}
// above part is already in the question. the second part i looped through the hashMap then the list once again, and checking if list and map entry have same group name, then made the startdate key that indexed element from the list.
HashMap<String, Map.Entry<String, ArrayList<Assignmentsdata>>> hashMapHashMap = new HashMap<>();
for (var entry : hashMap.entrySet()){
for( int j = 0; j<assignmentsdataArrayList.size();j++ ){
if (assignmentsdataArrayList.get(j).getGroupName()==entry.getKey()){
hashMapHashMap.put(assignmentsdataArrayList.get(j).getStartTime(),entry);
}
}
hashMapHashMap.put(entry.getValue().get())
}

Java - Iteration over arrayList & Insertion of 250k words into treeMap is taking huge time

I am implementing a Java based synonym finder, which will store the thesaurus of 250k words into a map and each associated googleWord into the txt file (1000 words in total) will be assigned as values for each of the thesaurus word if its the synonym of it.
Now, that I am doing that I am iterating over each Thesaurus word list and checking for its synonym using wordnet library and if the google word has one of those synonym word them I am assigning that value to Thesaurus map. Code block is provided below:
#SuppressWarnings("rawtypes")
public TreeMap fetchMap() throws IOException {
generateThesaurusList();
generateGoogleList();
/** loop through the array of Thesaurus Words..*/
for (int i=0; i<thesaurusList.size(); i++) {
SynonymFinder sf = new SynonymFinder();
// find the
ArrayList synonymList = sf.getSynonym(thesaurusList.get(i).toString().trim());
for (int j=0; j<synonymList.size(); j++) {
if (googleList.contains(synonymList.get(j)));
hm.put(thesaurusList.get(i).toString().trim(), synonymList.get(j).toString().trim());
}
}
return hm;
}
But, the iteration of the list and its insertion is taking very huge time. Can someone suggest something to cater it fast.
I have used HashMap for the same, but it was also slow..
Note: I must have to use some sort of map for storing data..
My change after suggestions, but nothing helped out.
#SuppressWarnings("rawtypes")
public TreeMap fetchMap() throws IOException {
generateThesaurusList();
generateGoogleList();
Set<String> gWords = new HashSet<>(googleList);
int record =1;
int loopcount=0;
ArrayList thesaurusListing = removeDuplicates(thesaurusList);
Map<String, Set<String>> tWordsWithSynonymsMatchingGoogleWords = new TreeMap<>();
/** loop through the array of Google Words..*/
for (int i=0; i<thesaurusListing.size(); i++) {
SynonymFinder sf = new SynonymFinder();
System.out.println(record);
// find the
ArrayList synonymList = sf.getSynonym(thesaurusListing.get(i).toString().trim());
for (int j=0; j<synonymList.size(); j++) {
if (googleList.contains(synonymList.get(j))) {
/**to avoid duplicate keys*/
tWords.put(thesaurusListing.get(i).toString().trim(), new HashSet<>(synonymList));
}
}
for (String tWord : tWords.keySet()) {
tWords.get(tWord).retainAll(gWords);
tWordsWithSynonymsMatchingGoogleWords.put(tWord, tWords.get(tWord));
}
record++;
}
return (TreeMap) tWordsWithSynonymsMatchingGoogleWords;
}
Your code was missing part of creation, entry which will consist of {key, set}, but was {key, value}. Based on what you want to achieve, you need to intersect two sets. Here is example how you can approach that:
public static Map<String, Set<String>> getThesaurusWordsWithSynonymsMatchingGoogleWords(
Map<String, Set<String>> tWordsWithSynonyms, Set<String> gWords) {
Map<String, Set<String>> tWordsWithSynonymsMatchingGoogleWords = new TreeMap<>();
for (String tWord : tWordsWithSynonyms.keySet()) {
tWordsWithSynonyms.get(tWord).retainAll(gWords);
tWordsWithSynonymsMatchingGoogleWords.put(tWord, tWordsWithSynonyms.get(tWord));
}
return tWordsWithSynonymsMatchingGoogleWords;
}
public static void main(String[] args) {
Map<String, Set<String>> tWords = new HashMap<>();
tWords.put("B", new HashSet<>(Arrays.asList("d")));
tWords.put("A", new HashSet<>(Arrays.asList("a", "b", "c")));
tWords.put("C", new HashSet<>(Arrays.asList("e")));
Set<String> gWords = new HashSet<>(Arrays.asList("a", "b", "e"));
System.out.println("Input -> thesaurusWordsWithSynonyms:");
System.out.println(tWords);
System.out.println("Input -> googleWords:");
System.out.println(gWords);
Map<String, Set<String>> result = getThesaurusWordsWithSynonymsMatchingGoogleWords(tWords, gWords);
System.out.println("Input -> thesaurusWordsWithSynonymsMatchingGoogleWords:");
System.out.println(result);
}
}
To make all things working, firstly you should trim you thesaurus words and find their matching synonyms.

Eliminate duplicates from hashmap list and count their support

I have a list of itemMap (Map<ArrayList<String>, Integer> itemMap = new HashMap<ArrayList<String>, Integer>() )
containing the following elments
{ [File3, File2]=4,
[File2, File3]=2,
[File1, File2]=6,
[File1, File3]=2,
[File3, File1]=6,
[File2, File1]=6 }
I want to obtain a list containing no duplicates. (in my case a duplicate is a list containing same elements of another list).Example (F1,F2) and (F2,F1) are the same in my work.
So I want to obtain the following result:
{ [File3, File2]=6,
[File1, File3]=8,
[File1, File2]=12 }
As you see I sum the counts of duplicates but I keep one of the duplicates in my hashmap.
Can anybody help me with a simple code and thank you.
My own try was a fail:
HashMap<List<String>,Integer> myobjectListB = new HashMap<List<String>,Integer>();
for (List <String> key : itemMap.keySet()){
for (List <String> y : itemMap.keySet()){
if((key.containsAll(y) && (!key.equals(y))) && (key.size())==y.size()) {
int count = itemMap.get(key)+itemMap.get(y);
myobjectListB.put(key, count);
}
}
}
System.out.println("object list"+ myobjectListB);
}
If you replace ArrayList with a HashSet it will work the way you intend it to. That's because the Map interface only stores one value per key, and it determines if two keys are equal using the equals method. Two ArrayLists containing the same objects in different order will return false when compared, but two HashSets containing the same objects in different order will return true
I have wrote a method where you get a new map without duplicates. When you add values to the new map, it always check if the list contains in the keyset and also check the swapped list is also contains in the keyset. So there won't be any duplicates.
import java.util.*;
public class Main {
public static void main(String[] args) {
Map<ArrayList<String>, Integer> itemMap = new HashMap<ArrayList<String>, Integer>();
itemMap.put(new ArrayList<>(Arrays.asList("File3", "File2")), 4);
itemMap.put(new ArrayList<>(Arrays.asList("File2", "File3")), 2);
itemMap.put(new ArrayList<>(Arrays.asList("File1", "File2")), 6);
itemMap.put(new ArrayList<>(Arrays.asList("File1", "File3")), 2);
itemMap.put(new ArrayList<>(Arrays.asList("File3", "File1")), 6);
itemMap.put(new ArrayList<>(Arrays.asList("File2", "File1")), 6);
System.out.println(removeDuplicates(itemMap));
}
static Map<ArrayList<String>, Integer> removeDuplicates(Map<ArrayList<String>, Integer> map) {
Map<ArrayList<String>, Integer> convertedMap = new HashMap<ArrayList<String>, Integer>();
for (ArrayList<String> list : map.keySet()) {
if (!convertedMap.keySet().contains(list)) {
Collections.swap(list, 0, 1);
if (!convertedMap.keySet().contains(list)) {
convertedMap.put(list, map.get(list));
}
}
}
return convertedMap;
}
}

HashMap values are changing without telling them to

I have a problem that I am unable to understand..
I am building a HashMap called wholeSetHistory.
I am building a HashMap with the same keys and values that wholeSetHistory has, called wholeSetHistoryT.
In a similar way I create two HashMaps called wholeSetRates, wholeSetRatesT
All HashMaps have this format HashMap<String, HashMap<String, Double>> .
I have this function that creates a train set
public void createTrainSet(HashMap<String, HashMap<String, Double>> wholeSetRates, HashMap<String, HashMap<String, Double>> wholeSetHistory){
for(String fbid : wholeSetHistory.keySet()){
ArrayList<String> locsBe = new ArrayList<>();
HashMap<String, Double> locss = wholeSetHistory.get(fbid);
HashMap<String, Double> locss2 = wholeSetRates.get(fbid);
for(String loc : locss.keySet()){
if(locss.get(loc)==1.0){
locsBe.add(loc);
}
}
ArrayList<Integer> randomNums = new ArrayList<>();
for(int i=0; i<2; i++){
Random rn = new Random();
int randomNum;
do{
int range = locsBe.size() - 1 + 1;
randomNum = rn.nextInt(range);
}while(randomNums.contains(randomNum));
randomNums.add(randomNum);
locss.put(locsBe.get(randomNum), 0.0);
locss2.put(locsBe.get(randomNum), 0.0);
wholeSetHistory.put(fbid, locss);
wholeSetRates.put(fbid, locss2);
}
randomNums.clear();
}
}
So, later on I am using it like this
(... creation of wholeSetHistory, wholeSetHistoryT, wholeSetRates, wholeSetRatesT)
System.out.println(wholeSetHistory.get("1"));//1
createTrainSet(wholeSetRatings, wholeSetHistory, nearUserIDWithVisitedTrueValues);
That means that I am passing to the function as paramater only wholeSetHistory
Although, later I
System.out.println(wholeSetHistory.get("1"));//2
System.out.println(wholeSetHistoryT.get("1"));//3
This is what happens:
The values that changes in wholeSetHistory changes in wholeSetHistoryT too!
For example, prints 2 and 3 are the same(!) and different from 1.
Any help is mych appreciated.
A reference points to a location in memory. If you add the same reference to two different data structures, altering the reference in one will also alter the other. They point to the same object in memory.

Creating Arrays with automated names?

I have a method in which I load tiles from a text file. The tiles are placed in an array when created, so that they can be cleared later. This has began to cause problems and I am wondering if there would be a way to create an array with a name that corresponds to the text file loaded. For example, I call
loadMap("map1");
With "map1" being the name of the txt file that the map is stored in. And if I were to call the loadMap method with the argument of "map1" how can I create an array titled something like "map1TileArray", or if the argument is "finalMap" I would want an array called "finalMapTileArray". Is it possible to do something like this, and if so, how?
EDIT:
I'm getting a NPE.
I declare my Map like this:
Map<String, ArrayList<Tile>> tileMap = new HashMap<String, ArrayList<Tile>>();
I then store an ArrayList in the tileMap with a string of the current map:
tileMap.put(map, tilearray);
But I get an error at this line:
if(tileMap.get(currentMap).size()>0) {
Which is the start of my unloadTiles method. currentMap is just the String for the map the program is on.
You will want to use a Map such as a HashMap, perhaps a Map<String, Integer[]>. This will allow you to create an array of Integer (or whatever) and associate it with a String.
For example:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Foo {
public static void main(String[] args) {
Map<String, Integer[]> myMap = new HashMap<>();
myMap.put("foo", new Integer[] { 1, 2, 3 });
myMap.put("bar", new Integer[] { 3, 4, 5 });
myMap.put("spam", new Integer[] { 100, 200, 300 });
for (String key : myMap.keySet()) {
System.out.printf("%8s: %s%n", key, Arrays.toString(myMap.get(key)));
}
}
}
Use a java.util.Map and assign the value to a variable. Probably you will be better if use a List instead of an array
List<Integer> currentArray = loadMap("map1");
....
// inside
private List<Integer> loadMap( String fileName ) {
List<Integer> result = allTheMaps.get( fileName );
if ( result == null ) {
// load it from file...
result = ....
allTheMaps.put( fileName, result );
}
return result;
}
As others have said, a map will work for this.
What others have not said is that you would probably also benefit from using a class to represent your tiles as well.
This way, any array logic you have for manipulating the tiles can be nicely encapsulated in one place. I would imagine something like this:
public class Tiles{
private int[] tiles;
private String name;
private Tile(int[] tiles, String name){
this.tiles = tiles;
}
public static Tiles getTiles(Map<String, Tiles> tilesCache, String tileName){
if (tilesCache.containsKey(tileName)){
return tilesCache.get(tileName);
}
// load from file
return tile;
}
public void clear(Map<String, Tiles> tilesCache){
tilesCache.remove(this.name);
this.tiles = null;
}
//Other logic about tiles
}
You might want to consider using a HashMap with a String as the key and an Integer[] for the value.
Map<String, Integer[]> maps = new HashMap<String, Integer[]>();
and when you call your loadMap function you could do something like this.
public Integer[] loadMap(String name) {
if (maps.contains(name)) {
return maps.get(name);
}
// Falls through if map is not loaded
int[] mapData = new int[##];
// load map
maps.put(name, mapData);
return mapData;
}

Categories

Resources