I'm making a game on Android Studio and it will have all sorts of items with their own values. I need to make a list of objects which can be modified from other classes. For example, I have class Tool and I want to make a list of Tool objects which I can modify from other classes.
This is what I've got so far:
public void StartGame() {
ArrayList<Tool> tools = new ArrayList<>(); //ID, Name, Owned, Fight, Resource, Building, Crafting, Clothing
tools.add(new Tool(1,"Hatchet",false,2,0,0,0,0));
tools.add(new Tool(2,"Pocket Knife",false,0,0,0,0,0));
}
For now I can create all the items when I start the game and modify the list from within the StartGame() itself. But what I want to achieve is that whenever the game starts I set all the list items value owned = false and whenever I need to, I can modify them once again.
Make Utils class like this.
public class Utils{
public static List<Tools> myList;
public static List<Tools> getMyList() {
return myList;
}
public static void setMyList(List<Tools> myList) {
test.myList = myList;
}
public static void changeLogic(){
//change ligic
}
}
and use Utils class where ever you want
Utils.setList(myList);
Related
I am trying to initialize objects in my ArrayList
The following is my code and what it does is that it receives an ArrayList, already defined in the main method. However, it is not executing the readInput method in the code below. readInput is a method declared in another class called customer that takes in keyboard input from the user. Its a complete class BTW. I believe that there is no object in the ArrayList at the moment as i have run some test to see whats the problem. Im new to using Arraylist. Therefoere i am unsure of how to solve this proble.
What custs.set(i, new customer()); does is actually to initialize the object in index.
public static void freeCustomer(ArrayList<customer> custs,
ArrayList<supplement>supps)
{
for(int i=0;i<custs.size();i++)
{
custs.set(i, new customer());
custs.get(i).readInput();
for(int s=0;s<supps.size();s++)
{
supps.set(s, new supplement());
supps.get(s).readInput();
}
}
}
If I understood right,you want to add user input from a customer method.I would use add method.I just made a fast example of add method.From here you can expand to loops,etc.
public static void freeCustomer(ArrayList<customer> custo,customer c)
{
custo.add(new customer(c.readInput()));
}
public static void main(String[] args) {
ArrayList<customer> custo = new ArrayList<customer>();
customer c=new customer("");
freeCustomer(custo,c);
}
}
Hello i am trying to familiarize myself with Java by doing a very simple "bankaccount" application and it doesn't even save to db or something so it resets all data on rerun.
The problem i am trying to find a good way of doing is that i have an ArrayList of accounts that i want to be able to access from any class so that during runtime for example after an deposit if i access that account later when i want to get balance i get an that account from the ArrayList and it is updated to the deposit value.
When googling i found this solution but i dont like it since it uses static ArrayList. is there any more elegant way than this for an applicaiton that only saves the state/data during runtime.
Simple class that adds the test accounts and so on where first value is acountId and second is balance
public class AccountsModel {
private ArrayList<AccountModel> listOfAccounts;
public AccountsModel() {
listOfAccounts = new ArrayList<AccountModel>();
listOfAccounts.add(new AccountModel(1,0));
listOfAccounts.add(new AccountModel(2,0));
listOfAccounts.add(new AccountModel(3,0));
listOfAccounts.add(new AccountModel(4,0));
}
public ArrayList<AccountModel> getListOfAccounts(){
return listOfAccounts;
}
}
Then in my main class i just do this
static AccountsModel accounts = new AccountsModel();
public static ArrayList<AccountModel> listOfAccounts = accounts.getListOfAccounts();
this "works" as i can get the same list from anywhere within the application. But is there any simple and elegant way of doing this some other way?
You said you dislike the static solution but to me "It needs to be accessed by many classes" screams static variables.
Basically, you create a wrapper for your ArrayList which carries out operations:
class AccountsModel {
private static ArrayList<AccountModel> singleton;
// a static constructor also wouldn't be a bad idea here
public static void init() {
/* add a bunch of AccountModels here*/
}
public static ArrayList<AccountModel> getAccounts() {
return singleton;
}
}
An example of a main method:
public static void main(String[] args) {
ArrayList<AccountModel> accounts = AccountModels.getAccounts();
}
I'm learning to code and currently I'm trying to clean up my massive code by finally learning classes. I'm telling you this just to give a heads-up my terminology might still be off :) :)
The situation
My code works with "layers" that will be drawn on top of each other
There are two types of layers: video layers and image layers.
Both types of layers are child from parent class "Layer"
They need to be run by creation order
The goal
I want to run a code for each item/object of the class.
current code
import java.util.*;
public class main {
public static void main(String[] args){
// defining the objects
LayerVideo item01 = new LayerVideo();
item01.path = "import/01/";
LayerVideo item02 = new LayerVideo();
item02.path = "import/02/";
LayerImage item03 = new LayerImage();
item03.path = "import/03/";
// here is the main goal:
// to run/call each object from class "Layer"
// "allLayers" does not exist, but that's what I don't know how to do.
allLayers.forEach( item ->{
System.out.println( item.path );
// expected result in console:
// import/01/
// import/02/
// import/03/
});
}
public static class Layer {
}
public static class LayerVideo extends Layer {
public String path;
}
public static class LayerImage extends Layer {
public String path;
}
}
Thoughts
How to get all excising objects from a class
If I have them, how to ID them?, by var name?
Could I sort/filter the objects in a loop?
Two things:
consider to make your classes top level ones. So don't go public static class LayerVideo inside your Main class. If they are that important, the classes should each go into their own java file.
then learn about Java collections to organized object instances. You could define use an ArrayList for example.
Beyond that, the point is probably: if you want common things for two different classes, then your base class needs to have that, like:
public abstract class Layer {
private String path;
public String getPath() { return path; }
public void setPath(String newPath) { path = newPath; }
and then your subclasses simply inherit that behavior.
Then, you simply can add objects with that extend that base type to a collection:
List<Layer> layers = new ArrayList<>();
Layer layer = new VideoLayer();
layers.add(layer);
So, with the help and pointers of #GhostCat I've came to the following working code:
main.java
public class main {
public static void main(String[] args){
// debug to see amount of elements in list
System.out.println( settings.layers.size() );
// Aggregate with .forEach(), but will switch to .stream() to also be able to filter
settings.layers.forEach( layer -> {
System.out.println( layer.path );
// do stuff
});
}
}
settings.java
import java.util.ArrayList;
import java.util.List;
public class settings extends main{
public static List<Layer> layers = new ArrayList<>();
static {
layers.add( new LayerImage(true, "input/01/", new int[] {255,255,255} ) );
layers.add( new LayerImage(false, "input/02/", new int[] {255,0,0} ) );
layers.add( new LayerVideo(true, "input/03/", new int[] {0,0,255} ) );
}
}
Layer.java
public abstract class Layer {
boolean run;
String path;
int[] color;
public Layer(boolean startRun, String startPath, int[] startColor) {
run = startRun;
path = startPath;
color = startColor;
}
}
LayerImage.java
public class LayerImage extends Layer {
public LayerImage( boolean startRun, String startPath, int[] startColor) {
super( startRun, startPath, startColor) ;
}
}
LayerVideo.java
public class LayerVideo extends Layer {
public LayerVideo( boolean startRun, String startPath, int[] startColor) {
super( startRun, startPath, startColor) ;
}
}
In the main.java I'll swap the aggregator .forEach() with .stream() later on. Sounds more flexible and to be able to filter the results in advance seems like a big advantage. (then I can also use the item.run to see if I want to run this layer).
Why is there a settings class? I want to be able to have ALL the settings and variables to set for the outcome in one file. This way I can (I think) quickly use different setting files. Maybe also change it to XML input later. Use a GUI or whatever. (You might think "ah, sweet summer child", I'll cross that bridge when I get there).
The Layer SuperClass will have around the 10 parameters/arguments in the constructor when finished. Feels a lot to change and maintaining for the SubClasses by passing it with super(); And later on make changes. What is I will have around, say, 20 SubClasses. Is there a more efficient way?
Any other pointers on what I can do better in this code above?
All in all a LOT learned today! Thanks everyone and special thanks to #GhostCat
I personally create an static ArrayList from the object for every class and add the objects to it in the constructor (with list.add(this)).
Like:
public class Layer{
static ArrayList<Layer> layerList = new ArrayList<>();
public Layer() {
layerList.add(this);
}
}
i am on the creation of an app in android. its a calculator app. the main activity is where the user could input the equation, and the second activity is where the user can add/edit/delete variables. so i made a new class in another file named Global.java. then i extended it to application, imported everything i need, made s private string, made some public functions, edited the manifest, and initialized it right on my main activity. everything works fine while im only using a string to be passed by the functions but when i started adding what i need, an ArrayList, and made some functions so i could access the list then run it, the app closes. i think its because the arraylist is not allowed to be passed to different classes? am i right or am i just missing something?
please dont downvote my post if i didn't post something needed. i am using aide so there is no log output. code:
Global.java
...
import android.app.*;
import java.util.*;
public class Global extends Application
{
private String s;
public static ArrayList<String> sList;
public String getS() {
return s;
}
public void setS(String ss) {
s=ss;
}
public void add() {
sList.add(s);
}
}
MainActivity.java
...
String s;
...
global=(Global)getApplicationContext();
...
global.setS("jian"); //this one works
global.sList.add("jian"); // this one dont
...
Are you sure you initialized sList, like this:
sList = new ArrayList<String>();
If you didn't, you might want to change its declaration to include this initialization.
public static ArrayList<String> sList = new ArrayList<String>();
Just do
global.add("jian");
since you have an add function to take care of the addition of item to arraylist.
Also, try with this:
public void add(String ss) {
sList.add(ss);
}
You are not instantiating your arraylist.
public static ArrayList<String> sList = new Arraylist<String>();
Also you should read beginner tutorials on Java and android, using a public extension of application like this is a bad idea and you can get log outputs from different apps if Aide doesn't provide that, search play store
Say you have the following java bean:
public class MyBean
{
private List<String> names = new ArrayList<String>();
public void addName(String name)
{
names.add(name);
fireNamesPropertyChange(name);
}
}
How would you normally implement a property change event for a collection? Do you try and use the index property which seems to be more for arrays than collections?
(NOTE: I updated this post after realizing a few mistakes of my own so this isn't the original but a more refined one instead)
For this purpose I'd do two new interfaces, ListListener and Listenable and then I would create a new class like ListenableArrayList which would wrap every List method with a call to one (or more) relevant methods defined in ListListener. In code it'd be something like this:
public class ListenableArrayList<T> extends ArrayList<T>
implements Listenable<T> {
private ArrayList<T> internalList;
private ListListener<T> listener;
/* .. */
public void add(T item) {
listener.beforeAdd(T item);
internalList.add(item);
listener.afterAdd(T item);
}
/* .. */
public void setListener(ListListener<T> listener) {
this.listener = listener;
}
}
public interface ListListener<T> {
/* .. */
void beforeAdd(T item);
void afterAdd(T item);
/* .. */
}
public interface Listenable<T> {
/* .. */
void setListener(ListListener<T> listener);
/* .. */
}
The reason I'd do it this way would be to allow for creating truly ad-hoc listeners on the fly instead of tying the ListenableArrayList to some specific implementation. For example with this the following would be possible:
Listenable<String> list = new ListenableArrayList<String>();
list.setListener(new ListListener<String>() {
#Override
public void beforeAdd(String item) {
System.out.println("About to add element "+item+"...");
}
#Override
public void afterAdd(String item) {
System.out.println("...element "+item+" has been added.");
}
});
A bit cluttered, maybe but on the other hand this would allow for easy extension to Collections, Sets and whatnot rather easily.
Take a look at Glazed Lists library, which has support for observable collections.
If I were to do it myself, I would likely create custom Listener interface with elementsAdded, elementsRemoved methods, or similar :-) (also depending on my needs)
You can use an Observable Collection: https://commons.apache.org/dormant/events/apidocs/org/apache/commons/events/observable/ObservableCollection.html
Normally I'd do the following:
public class MyBean {
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private List<String> names = new ArrayList<String>();
public void addName(String name) {
names.add(name);
pcs.firePropertyChange("names", null, Collections.unmodifiableList(names));
}
public void addPropertyChangeListener(PropertyChangeListener l) {
pcs.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
pcs.removePropertyChangeListener(l);
}
}
PropertyChangeSupport manages the listeners and fires the events on your behalf.
By passing null as the "old value" it forces the event to be fired. (It's likely that listeners won't really care about the old value anyway)
JDK 7+ solution:
import javafx.collections.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("s1");
list.add("s2");
ObservableList<String> observableList = FXCollections.observableList(list);
observableList.addListener(new ListChangeListener<String>() {
#Override
public void onChanged(Change<? extends String> change) {
while(change.next()){
System.out.println("added: " + change.getAddedSubList());
}
}
});
observableList.add("s3");
}
}
For a swing GUI event I'd normally just use an EventListenerList to do the work for me.
EDIT: on the rephrase of the questions: how do you treat collections, I'd usually use an event similar to the collections type, so for example a TreeModel event usually takes a TreePath argument, or for something in a map I'd indicate the key.
However for simple JavaBeans the most common is assume a list/array and just use the index.
Methinks you will need fireNamesPropertyAdd, fireNamesProperyDelete. A list level notification will IMHO not work, even if it was an array and an index was added as it can't handle deletes. If the element at some index can be changed, you will also need fireNamesProperyChange. It might be useful to have index as parameter in addition to the string value.
Are you perhaps looking for java.beans.PropertyChangeSupport?
In my opinion, you should avoid PropertyChangeEvent. IndexedPropertyChangeEvent is worse, and very infrequently used by Swing anyway. It's better to narrow the focus of your types, and fire a javax.swing.event.ChangeEvent or similar (even just call a Runnable).
For certain types (like lists!), Glazed Lists (or equivalent) mentioned in another post by Peter Štibraný seem like a good way to go.