HashMap of ArrayList as the value initialization - java

I am trying to make a HashMap that takes the value as a List<Pack> where Pack is an object that I created, then adds Packs to this list if the condition is true.
Now I get errors even though the condition is true, and I think I did not initialize it correctly can someone tell me where the problem is?
static HashMap<Long, List<Pack>> ackPkts = new HashMap<Long, List<Pack>>();
static HashMap<Long, List<Pack>> dataPkts = new HashMap<Long, List<Pack>>();
static List<Pack> pktList = new ArrayList<Pack>();
if((msg.getPayloadLength()) == 0 && (msg.isSYN()) == false && (msg.isACK()) == true){
Pack pack = new Pack(msg.getAck(), msg.sackPresent(), captureTime, srcIP, destIP, msg.isSYN());
(ackPkts.get(msg.getAck())).add(pack);
} else {
Pack pack = new Pack(msg.getSeq(), captureTime, srcIP, destIP,
msg.getPayloadLength(), msg.isSYN());
(dataPkts.get(msg.getSeq())).add(pack);
}

The List<Pack> in your HashMaps are never defined. They are of the interface list but nowhere you identify what kind of List they are. You have to follow a structure as follows:
Map<long, List<Pack>> map = new HashMap<>() // java 7 syntax
List<Pack> packets = new ArrayList<>();
packets.add(pack);
map.put(msg.getAck(), packets);
When adding an element to the ´List´, which you now can because it exists, you do:
map.get(msg.getAck()).add(pack);

You want to put List instances in first Maps before you use add() on them:
static List<Pack> datapktList = new ArrayList<Pack>();
static List<Pack> actpktList = new ArrayList<Pack>();
Then add respective List instance to Map:
ackPkts.put(msg.getAck(), datapktList );
dataPkts.put(msg.getAck(), actpktList );
Then following would work:
(ackPkts.get(msg.getAck())).add(pack);
(dataPkts.get(msg.getSeq())).add(pack);

Related

How can I make a new HashMap that won't change the one I've copied from?

I have a HashMap called the Item Database, which stores data about all of the items.
However, these items can have modifiers (in this case, the stat multiplier is important). Whenever I change an item to just one specific item drop, it ends up changing the base item from the HashMap.
For example, whenever a player creates a Katana, it does something like this.
HashMap<String, CustomItem> db = new HashMap<String, CustomItem>();
db.putAll(ItemDatabase.database);
CustomItem ci = db.get("KATANA");
From there, modifiers are applied via a getBukkitItem function on the CustomItem ci, basically multiplying a lot of the stats on that CustomItem and applying it.
baseHealth = (int) ((abbaseHealth / 100.0) * multiplier);
and other stats like that.
However, whenever I make changes to this new CustomItem, it also applies to the ItemDatabase hashmap. This means that whenever somebody makes another Katana, those multiplied stats become the new base stats to be multiplied.
TL;DR Whenever I'm changing a variable I got from a HashMap (db), that change also applies to the HashMap (itemdb). This happens even if the HashMap (db) it's from, is a copy of another HashMap (itemdb)
I have tried the method above, and using .clone() on a HashMap and casting it back to HashMap. Unfortunately I'm not really sure what else to try.
you should create a new object of deep clone. Using orika framework like below.
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
#Test
public void t() {
Map<Integer, User> map = new HashMap<>();
User one = new User();
one.setName("one");
System.out.println(one);
User two = new User();
two.setName("two");
System.out.println(two);
map.put(1,one);
map.put(2,two);
TypeBuilder<Map<Integer,User>> typeBuilder = new TypeBuilder<Map<Integer,User>>() {
};
Type<Map<Integer,User>> type = typeBuilder.build();
Map<Integer,User> copyMap = mapperFactory.getMapperFacade().mapAsMap(map, type,type);
System.out.println(copyMap.get(1));
System.out.println(copyMap.get(2));
}
You need to make new CustomItem instances. If you only make a copy of the Map, you’re just copying the references stored in the Map; they’ll still refer to the same CustomItem instances.
You can make this easier by adding a copy constructor or clone() method to CustomItem. Example of a copy constructor:
public class CustomItem {
public CustomItem(CustomItem other) {
this.name = other.name;
this.baseHealth = other.baseHealth;
this.multiplier = other.multiplier;
// Don't want two instances to refer to the same List!
this.inventoryList = new ArrayList<>(other.inventoryList);
// etc.
}
}
Example of a clone() method:
public class CustomItem
implements Cloneable {
#Override
public CustomItem clone()() {
try {
CustomItem copy = (CustomItem) super.clone();
// Don't want two instances to refer to the same List!
copy.inventoryList = new ArrayList<>(copy.inventoryList);
// etc.
return copy;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
Once you have a way to copy CustomItem instances, you need to use it in your new Map:
Map<String, CustomItem> newMap = new HashMap<>();
for (Map.Entry<String, CustomItem> entry : db) {
String key = entry.getKey();
CustomItem value = entry.getValue()
value = value.clone();
newMap.put(key, value);
}
A shorter way:
Map<String, CustomItem> newMap = new HashMap<>(db);
newMap.replaceAll((k, v) -> v.clone());

Adding value to list object in hash-map

I'm trying to add list object to hashmap
I tried with the following code didn't worked
public static Map<Long, List<Long>> getCellAttributes(List<Vo> voList){
LOG.info("VO: {}", Arrays.toString(VO.toArray()));
Map<Long, List<Long>> atributesMap = new HashMap();
List<Long> cellList = new ArrayList<>();
for(: VOList){
Long cID = VO.getID();
Long cellUserNumber = VO.getCellNumber();
if(cellMap.containsKey(ID)){
cellList.add(cellNumber);
cellmap.put(ID, list);
}
else {
Map.put(ID, cellAtributesMap.get(ID).add(cellNumber));
}
}
return cellMao;
}
Found below error for else block part.
Wrong 2nd argument type. Found: 'boolean', required:
Ok, first off, what is Map.put in the else block? To me it sounds wrong logically, probably you meant the case where the campaignId is not in the map yet.
In this case, you can just:
else {
List<Long> cellList = new ArrayList<>();
cellList.add(cellUserNumber);
cellAtributesMap.put(campaignId, cellList);
}
Now the if block also looks logically wrong, there is no need to maintain a global list (what if the targetedOffersCampaignVOList is not ordered) and there is no need to put every time into the map.
Since it doesn't seem to be a homework for me, here is a better version:
Map<Long, List<Long>> cellAtributesMap = new HashMap();
// note, the following line is not required and should be removed
//List<Long> cellList = new ArrayList<>();
for(TargetedOffersCampaignVO targetedOffersCampaignVO: targetedOffersCampaignVOList){
Long campaignId = targetedOffersCampaignVO.getCampaignID();
Long cellUserNumber = targetedOffersCampaignVO.getCellUserNumber();
if(cellAtributesMap.containsKey(campaignId)){
// the list in the value already exists anyway, just add a new cell user number to it
cellAttributesMap.get(campaignId).add(cellUserNumber);
}
else {
// create a new key-value pair in the result map
// and add one element which is a current cellUserNumber to it
List<Long> cellList = new ArrayList<>();
cellList.add(cellUserNumber);
cellAtributesMap.put(campaignId, cellList);
}
}
return cellAtributesMap;
I think you have problem in your else block:
else {
Map.put(campaignId, cellAtributesMap.get(campaignId).add(cellUserNumber));
}
Map call here is in inappropirate. If my guess is correct, you want to initialize a new array if that particular campaignId does not exist in previously, in that case you want to execute this else block. Then you just change your else block like this:
else
{
List<Long> newList= new ArrayList<>();
newList.add(cellUserNumber);
cellAtributesMap.put("campaignId", newList);
}
cellAtributesMap.get(campaignId).add(cellUserNumber)
Above method call returns a boolean value.
Your else block should be like below
List<Long> list=new ArrayList<>();//any list implementation
list.add(cellUserNumber);
cellAtributesMap.put(campaignId,list);

How to modify ArrayList object if one of its field contain duplicate entries?

I have an ArrayList of type model class .Model class contain two fields
for Ex: number and name.
If the number is appearing multiple times then I need to append its corresponding name so that the number has to be a unique in ArrayList?
Lets say:
list.get(0).getNumber = 100,
list.get(0).getName = Narendra.
list.get(1).getNumber = 100,
list.get(1).getName = Modi.
list.get(2).getNumber = 101,
list.get(2).getName = xyz.
So my final list should contain only two items i.e.
list.get(0).getNumbet =100,
list.get(0).getName = Narendra Modi.
list.get(1).getNumbet =101,
list.get(1).getName = xyz.
It appears that what you really want is a multi-map. You can do this in plain Java 8 with
final Map<Integer, Set<String>> map = new HashMap<>();
public void put(Integer num, String name) {
map.computeIfAbsent(num, n -> new HashSet<>()).add(name);
}
put(100, "Narendra");
put(100, "Modi");
put(101, "xyz"):
With traditional java versions, you can use map as below:
Map<Integer, String> m = new HashMap<Integer, String>();
if(m.get(100) != null){
m.put(100,"Narendra");
}
else{
m.put(100, (m.get(100)+" Modi"));
}

TreeMap using a string key and an arraylist

I am brand new to using collections, so I am confused on how to do this. I am trying to use a TreeMap to hold a word as the key and then an ArrayList to hold one or more definitions for the word.
public class Dict {
Map<String, ArrayList<String>> dic = new TreeMap<String, ArrayList<String>>();
public void AddCmd(String word, String def) {
System.out.println("Add Cmd " + word);
if(dic.get(word)==null){
dic.put(word, new ArrayList.add(def));
}
}
}
I am getting an error on "new ArrayList.add(def)". I thought this was the correct way to do this, but I am obviously wrong. Does anyone have any ideas as to what I am doing wrong?
Calling ArrayList#add returns a boolean which is not the desired value for your Map, thus getting the compiler error.
You need to insert the ArrayList and then add the element. Your code should look like this:
ArrayList<String> definitions = dic.get(word);
if (definitions == null) {
definitions = new ArrayList<String>();
dic.put(word, definitions);
}
definitions.add(def);
dic.put(word, new ArrayList.add(def)); is the culprit.
since you have declared map to take Arraylist of string as a value. the value to pass for map must be Arraylist of string.
but this line is adding a value as new ArrayList.add(def) since you are trying to create a list and adding element , add method returns boolean -> true if it can add false if it fails.
so it means value to the map is going as a boolean not as arraylist which is against the map declaration.
so use code as below
ArrayList<String> listOfString = dic.get(word);
if (listOfString == null) {
listOfString = new ArrayList<String>();
listOfString .add(def);
}
dic.put(word, listOfString );
You have to break it up, because add does not return the original ArrayList:
ArrayList<String>> NewList = new ArrayList<String>();
NewList.add(def);
dic.put(word, NewList);
You are not actually creating a new ArrayList. Try this:
ArrayList<String> newDef = new ArrayList<String();
newDef.add(def);
dic.put(word, newDef);

LinkedHashMap with ArrayList - How to load ArrayList?

I am fairly new to Java and am trying to load a LinkedHashMap that contains an ArrayList of values. I am trying to load the values from a query result from an API based query result (Salesforce).
Here is the error: "Cannot refer to a non-final variable breakdown inside an inner class defined in a different method" - the breakdown variable is underlined in red giving this message, Ive noted the line in concern below.
CODE
public LinkedHashMap<String, ArrayList<String>> sfFundIdsByContact;
public ArrayList<String> getFundsIDsForContact(Contact aContact)
{
QueryResult queryResults = null;
ArrayList<String> ids = new ArrayList<String>();
int index = 0;
Boolean done = false;
String contactid = aContact.getId();
String SCCPBId = null;
if(sfFundIdsByContact == null || sfFundIdsByContact.size() <= 0){
//Do the Salesforce API CALL and Return the results
...
while (! done)
{
SObject[] records = queryResults.getRecords();
for ( int i = 0; i < records.length; ++i )
{
if(sfFundIdsByContact.containsKey(breakdown.getSalesConnect__Contact__c())){
sfFundIdsByContact.get(breakdown.getSalesConnect__Contact__c()).add(breakdown.getId());
} else {
//Line below in the add(breakdown.getId() - contains the error
sfFundIdsByContact.put(breakdown.getSalesConnect__Contact__c(), new ArrayList<String>() {{ add(breakdown.getId()); }});
}
}
All suggestions are appreciated.
In your else block, instead of:
new ArrayList<String>() {{ add(**breakdown.getId()**); }}
you can use:
new ArrayList<String>(Arrays.asList(breakdown.getId())
or, since you just want a single element ArrayList, you can use Collections.singletonList that avoids the creation of temporary varargs array:
new ArrayList<String>(Collections.singletonList(breakdown.getId())
The { ... } after the new ArrayList<>() creates an anonymous subclass of ArrayList, which is an inner class only. Inside an inner class you cannot access non-final local variables.
You can ease the code by always retrieving the List value in the for loop, then if it is null create a new one and add it to your Map, otherwise add the value to the list.
for (int i = 0; i < records.length; i++) {
List<String> value = sfFundIdsByContact.get(breakdown.getSalesConnect__Contact__c());
if (value == null) {
value = new ArrayList<String>();
sfFundIdsByContact.put(breakdown.getSalesConnect__Contact__c(), value);
}
value.add(breakdown.getId());
}
As a recommendation, change the definition of
LinkedHashMap<String, ArrayList<String>> sfFundIdsByContact
to
Map<String, List<String>> sfFundIdsByContact
Refer to What does it mean to "program to an interface"?

Categories