Appending my sessionId to an arrayList - java

Each time a new session id is created i need to save them in an array or a list, to have it as a reference.
Correct me where am i wrong
public static void main(String args[]) {
//creating an arrayList
ArrayList<String> myList = new ArrayList<String>();
try {
// calculate the sessionId
String sessionId = "b03c0-000-5h6-" + uuid.substring(0,4) + "-000000000";
myList.add(sessionId);
} catch(Exception e){
e.printStackTrace();
}
}
the elements in my arrayList are getting replaced and not appended.
Where am i wrong

You are wrong.
The List interface is designed store the values with duplicates. So you will append. If you want only unique results use Set instead.
Collection<String> myList = new HashSet<String>();
Note that List and Set are math concepts that both represent collections. In Java Collection Framework those concepts ware reproduces as classes and interfaces.
The Collection<T> is the super interfaces of Set and List. This allow you to change the behavior of your program depending on implementation.
You should also avoid using class names in variables, to have that flexibility.
If you want to "tell" other developers that the session ids storage store only unique values use
Set<String> sessionsIDs = new HashSet<String>();
If you want to "tell", that storage is in form of list (that allow repetitions) use
List<String> sessionsIDs = new ArrayList<String>();
If you want to keep that detail of implementation hidden, use collection
Collection<String> sessionsID = crateSessionStorage();
private Collection<String> crateSessionStorage() {
boolean useUniqueStorage = isUniqueStorage();
if(UseUniqueStorage) {
return new HashSet<String>();
}
return new ArrayList<String>();
}

The creation/initialization of myList in your code results to undesired behavior.
Your ArrayList can be a static instance attribute of your class instead of getting created everytime the method is invoked.

String sessionId = "b03c0-000-5h6-" + uuid.substring(0,4) + "-000000000"; myList.add(sessionId); this put in loop other when you call main() it replace full arraylis

It is happening because you are creating every time new object
ArrayList<String> myList = new ArrayList<String>(); // creates an object evrytime whem main will be called.
try {
String sessionId = "b03c0-000-5h6-" + uuid.substring(0,4)
/* from where uuid is comming?? */
+ "-000000000";
myList.add(sessionId);
// thiss will add inside new arraylist not in previous,
// because everytime it is getting new object reference
} catch(Exception e){
e.printStackTrace();
}
}

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());

Saving data in ArrayList of objects

Im trying to figure out how to save some data in ArrayList of objects, but I'm new in Java so I have had some trouble...
So lets say we have an ArrayList of this object:
public class AppListModel(){
private String AppName;
private String packageName;
public AppListModel(){
}
public String getAppName() {
return appName;
}
public String getPackageName() {
return packageName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
}
and we have arrayList of this object in difrent file:
public class ProfilesList {
private ArrayList<AppListModel> profilesList = new ArrayList<AppListModel>();
public ProfilesList(){
}
public ArrayList<AppListModel> getProfilesList() {
return profilesList;
}
public void setProfilesList(ArrayList<AppListModel> profilesList) {
this.profilesList = profilesList;
}
public void addProfilesList(AppListModel appListModel) {
this.profilesList.add(appListModel);
}
}
Is it possible to store data in one file like:
AppListModel appList = new AppListModel();
appList.setAppName("ssss");
appList.setPackageName("ddddd");
ProfilesList list = new ProfilesList();
list.addProfilesList(appList);
and then access those data from another file like:
ArrayList<AppListModel> list = new ArrayList<AppListModel>();
ProfilesList profList = new ProfilesList();
list = profList.getProfilesList();
Does the ArrayList named list from last code sample now contain those previously created data?
If not, how can be something like that achieved? do I need use soma databases or something?
I want to use it to process ArrayList between different activities in android.
Thankyou!
If you want to access data from different parts of your app, I would suggest you use SharedPreferences. More information on this can be found here. SharedPreferences are more useful for key-value pairs, however.
In your case, an SQLite database would be more useful. See here. You would create an SQLite table that contains columns for each of your object's fields. For example, a table with columns named AppName, PackageName, etc.
You could simply pass the ArrayList to different parts of your app as an argument, but if you begin dealing with multiple lists, this can be cumbersome and ineffective. The SQLite database will be much more efficient as your app grows.
The "new" keyword creates a new instance of the object (in this case, being a collection, an empty one).
If you want to access the same instance you created before, you need to "pass" it to the point where it's needed. Say that your usage code is wrapped in a function:
void doSomething(ProfilesList profList) {
ArrayList<AppListModel> list = new ArrayList<AppListModel>();
list = profList.getProfilesList();
//do something with list...
}
Then you can call this code by doing something like:
AppListModel appList = new AppListModel();
appList.setAppName("ssss");
appList.setPackageName("ddddd");
ProfilesList list = new ProfilesList();
list.addProfilesList(appList);
doSomething(list);
The list you make here:
AppListModel appList = new AppListModel();
appList.setAppName("ssss");
appList.setPackageName("ddddd");
ProfilesList list = new ProfilesList();
list.addProfilesList(appList);
Won't be the same as the list here:
ArrayList<AppListModel> list = new ArrayList<AppListModel>();
ProfilesList profList = new ProfilesList();
list = profList.getProfilesList();
Anytime you make a new ProfilesList() it is not the same as any other.
public void anyMethod() {
//list1 is not the same as list2
ArrayList<AppListModel> list1 = new ArrayList<AppListModel>();
ArrayList<AppListModel> list2 = new ArrayList<AppListModel>();
//list3 will be same as list1
ArrayList<AppListModel> list3 = list1;
//adding an AppListModel to list1
AppListModel appList = new AppListModel();
list1.add(appList);
list1.getProfilesList().isEmpty(); //false because it has appList
list2.getProfilesList().isEmpty(); //true
list3.getProfilesList().isEmpty(); //false because it refers to list1 which has appList
}
The above shows the difference between the ArrayLists.
"new" will always create a new instance of the wanted object.
You want to look up SQLite. It's how you store data in android. http://developer.android.com/training/basics/data-storage/databases.html
Once it's saved on your local phone's database you can retrieve data whenever you want and add it to wanted array lists. However, any changes to the data needs to be committed to the database again for it to be stored permanently.
Does the ArrayList named list from last code sample contain those previously created data?
If you use this code:
ProfilesList profList = new ProfilesList();
ArrayList<AppListModel> list = profList.getProfilesList()
You will not get any previously saved data as you have created a new instance of a ProfilesList object. You'd need to use the same instance to get the data back
ProfilesList profList = new ProfilesList();
profList.addProfilesList(...);
//...
//This would then return the correct data
ArrayList<AppListModel> list = profList.getProfilesList();
I would suggest using a SQLite database if you require more persistent storage

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);

Removing common elements between two different Arraylist

I have read several posts for this but not getting the exact thing I am looking for. I know how to develop a complex logic for this, this is for Android and we can't expect too much processing on the device due to the limited resources available.
I have an ArrayList of an bean class objects consisting five fields as
Java Bean -- MyShares
fileName
filePath
fileSize
isShared
Creator
I have another ArrayList of String which contains only filepaths. Now what I want is to remove all the common elements between the two arraylist means the file paths in seconds arraylist and file path in first arraylist objects are similar then I have to remove from both of the arraylist but I don't want a new arraylist which contains the uncommon elements. But I want to get my both arraylist only without their common elements.
You could use a Map from String to your object type (I used Obj in order to make a SSCCE).
Assume we are given a list objects and a list strings.
Steps:
Put all objects in a map with their str variable as key
Get all those str variables using map.keySet()
Get all strings that are in objects but not in strings by keys.removeAll(strings)
Get all strings that are in strings but not in objects by strings.removeAll(keys)
Get the objects that correspond to the remaining keys
Note that you need to be careful in steps 3 and 4, because you need to back up one of the collections.
import java.util.*;
public class Test {
public static void main(String[] args) throws Exception {
new Test();
}
public Test() {
List<Obj> objects = new ArrayList<>();
objects.add(new Obj("a"));
objects.add(new Obj("b"));
objects.add(new Obj("c"));
List<String> strings = new ArrayList<>();
strings.add("a");
strings.add("d");
strings.add("e");
remove(objects, strings);
System.out.println(objects);
System.out.println(strings);
}
public void remove(List<Obj> objects, List<String> strings) {
Map<String, Obj> map = new HashMap<>();
for (Obj object : objects) {
map.put(object.str, object);
}
Set<String> keys = map.keySet();
List<String> oldStrings = new ArrayList<>(strings);
strings.removeAll(keys);
keys.removeAll(oldStrings);
objects.clear();
for (String key: keys) {
objects.add(map.get(key));
}
}
public class Obj {
public String str;
public Obj(String str) {
this.str = str;
}
#Override
public String toString() {
return str;
}
}
}
Prints:
[b, c]
[d, e]
Rough Java code:
HashSet<String> commonKeys = new HashSet();
for (Share share : shares) {
commonKeys.add(share.filePath);
}
commonKeys.retainAll(filePaths);
for (Iterator<Share> it = shares.iterator(); it.hasNext(); ) {
Share share = it.next();
if (commonKeys.contains(share.filePath)) {
it.remove();
}
}
filePaths.removeAll(commonKeys);
This won't be O(N) because remove on an ArrayList is expensive. To get O(N) behavior you either need to create new ArrayList instances, or add the elements you don't want removed to temporary lists, and then clear() and add them back into the original lists.
I will go with some clues for you
Suppose you have two lists one for bean objects namely myBeans and another for filePaths namely filePaths
List<MyBean> beansToRemove = new ArrayList<MyBean>();
List<FilePath> filePathsToRemove = new ArrayList<FilePath>();
for(Bean myBean : myBeans) {
for(FilePath filePath : filePaths) {
if(myBean.getfilePath.equals(filePath.getFilePath())) {
beansToRemove.add(myBean);
filePathsToRemove.add(filePath);
}
}
}
//Now remove filePaths and beans if any
for(Bean myBean : beansToRemove) {
myBeans.remove(myBean);
}
for(FilePath filePath : filePathsToRemove) {
filePaths.remove(filePath);
}
it is just a flow to make you clear for what to do; you can further customize it according to your needs.
You can use an outer loop to scan over the Bean objects, and an inner loop to scan over the file paths.
pseudo code:
for (Bean i in beans) {
for (String p in paths) {
if (i.path.equals(p)) {
beansToRemove.add(i);
pathsToRemove.add(p);
}
}
}
beans.removeAll(beansToRemove);
paths.removeAll(pathsToRemove);
I'm not sure if my extra arraylists to track the removed arraylists go against your question or not since the original arrays remain.
If you presort both arrays on the path and keep track of the position in each area (not exhaustive search) you can improve it from n2 to nlgn

How to remove multiple elements in Vector in Java?

I read from .txt file all of the ids and insert these ids into Vector.
String pathSelectedfile = fileChooser.getSelectedFile().getAbsolutePath();
File selectedFile = new File(pathSelectedfile);
Scanner readFile = new Scanner(selectedFile);
Vector ids=new Vector();
while (readFile.hasNextLine()) {
String id= readFile.nextLine();
ids.addElement(id);
}
then I want to remove multiple ids in Vector.i can do that by for loop
but information is too big.tnx a lot
To remove multiple values
Vector vector = new Vector();
vector.add("value1");
vector.add("value2");
vector.add("value3");
vector.add("value4");
System.out.println("Size : "+vector.size());
// to remove single value
vector.remove("value1");
System.out.println("Size : "+vector.size());
Vector itemsToRemove = new Vector();
itemsToRemove.add("value3");
itemsToRemove.add("value4");
//remove multiple values
vector.removeAll(itemsToRemove);
System.out.println("Size : "+vector.size());
//to remove all elements
vector.removeAllElements();
// or
vector.clear();
But instead of using Vector consider to use ArrayList since Vector is obsolete collection.
Read this : Why is Java Vector class considered obsolete or deprecated?
Also use generics Like ArrayList<String> idList = new ArrayList() if you store only String elements in list.
If you want to skip duplicates when adding elements in Vector, use the following code
Vector vector = new Vector() {
#Override
public synchronized boolean add(Object e) {
if(!contains(e)){
return super.add(e);
}
System.out.println("Element " + e +" is duplicate");
return false ;
}
};
But if you want to add only unique elements, use Set
Do completely remove the duplicated ids, you could use the following:
Set<String> ids=new LinkedHashSet<String>();
Set<String> duplicates=new HashSet<String>();
while (readFile.hasNextLine()) {
String id= readFile.nextLine();
if(!ids.add(id)) {
duplicates.add(id);
}
}
ids.removeAll(duplicates)
Note that unlike Vector, LinkedHashSet is not synchronized. In most cases this is not a bad thing, but in the case that you actually need it to be synchronized, wrap it using Collections.synchronizedSet()
READ the javadoc and pay attention to methods starting with remove http://docs.oracle.com/javase/6/docs/api/java/util/Vector.html. This should be you first approach not SO.
If you "want to remove multiple ids in Vector" do the following
ids = new Vector(new HashSet(ids))

Categories