I have a Class and this Class constructs 7 ArrayLists:
public class Fruchtplanungsmodul {
private ArrayList<Crops> fruchtliste1F;
private ArrayList<Crops> fruchtliste2F;
private ArrayList<Crops> fruchtliste3F;
private ArrayList<Crops> fruchtliste4F;
private ArrayList<Crops> fruchtliste5F;
private ArrayList<Crops> fruchtliste6F;
private ArrayList<Crops> fruchtliste7F;
// Constructor
public Fruchtplanungsmodul() {
fruchtliste1F = new ArrayList<>();
fruchtliste2F = new ArrayList<>();
fruchtliste3F = new ArrayList<>();
fruchtliste4F = new ArrayList<>();
fruchtliste5F = new ArrayList<>();
fruchtliste6F = new ArrayList<>();
fruchtliste7F = new ArrayList<>();
}
functions for deleting Objects....
}
And I want to load Objects in this list with Drools-rules.
I do load the same Objecttyps into all Arraylists. For example, in this rule, I load 4 Objects Crops into the first ArrayList.
rule "Körnerlegmunosen: Planung erste Feldrigkeit"
when
//$grund: Grundbedingung(grundbedingung == 1)
$feld: Feldrigkeit(feldrigkeit1 == "Körnerleguminosen")
$m: Fruchtplanungsmodul()
then
Crops erbse = new Crops("Erbse", "Koernerleguminose","BF", "Hafer", "Silomais", "Sommerung", 6);
Crops ackerbohne = new Crops("Ackerbohne" , "Koernerleguminose", "BF", "Silomais", "Wintergerste", "Sommerung", 4);
Crops lupine = new Crops("Lupine", "Koernerleguminose", "BF", "Späte Kartoffel", "Winterroggen", "Sommerung", 4);
Crops sojabohne = new Crops("Sojabohne", "Koernerleguminose", "BF", "Futterrübe", "winterroggen", "Sommerung", 3);
insert(erbse);
insert(ackerbohne);
insert(lupine);
insert(sojabohne);
$m.addFrucht1(erbse);
$m.addFrucht1(ackerbohne);
$m.addFrucht1(lupine);
$m.addFrucht1(sojabohne);
end
In other rules, I load different Crops into other ArrayLists from the Class Fruchtplanungsmodul().
My Question is: Is there any way to compare Objects from different ArrayLists?
For example, ArrayList "fruchtliste2F" has 4 objects from the type Crops and the ArrayList "fruchtliste3F" also has 4 objects from the type Crops. Now I need to check with a rule if there is one Object with the same Name in both ArrayLists. If this is true, the rule should delete the object from the second list.
Thanks for your help!
Philipp
If the arrays you want to check are fixed (i.e. you always want to check array #2 with array #3), then you can do something like this:
rule "Delete duplicated"
when
$f: Fruchtplanungsmodul()
$c1: Crop() from $f.fruchtliste2F
$c2: Crop(name == $c1.name) from $f.fruchtliste3F
then
//If you want to remove the fact you have inserted too:
delete($c2);
//Remove the object from the array
$f.deleteFrucht3($c2);
end
If you want to check all the arrays, then you either create copies of the rule above, or create a way your java class to access the arrays by an index and create a generic rule to compare them all.
Hope it helps,
Related
I am running into problem with a code for a text-based game. My class Locations is meant to load parameters from a "config" text file to create objects.
My current approach is:
I have created a public class with a constructor that will take the parameters of the object (location). It assigns them as this.xxx to private variables.
I have also created a public static class that parses the file, and once it has the necessary amount of parameters to create an object, it creates one by passing them to the constructor. Next, it adds that object to an ArrayList locations_list. Once all location objects were generated, the class returns the ArrayList locations_list
My static class parses the text file OK. However, when I run a test which iterates through locations_list and calls the getters for each element, the ArrayList parameters of objects are not individualized. All of the ArrayList elements return the same locations_characters.
The location_characters of all objects will have the same content, which is a list containing "characters" of all locations.
For example, if location 1 has characters 2 and 3 and location 2 has 6 and 7, my location_characters will print [2,3,6,7].
If I put a location_characters.clear(); after adding to location_list, the location_characters becomes empty for all objects.
Sample code snippets:
Public class with a constructor:
public class Locations {
private final int location_id;
private final String location_name;
private final String location_description;
private ArrayList <Integer> location_characters;
private ArrayList <Integer> location_items;
private final ArrayList <Integer> location_enter_from;
private final ArrayList <Integer> location_exit_to;
private String location_stage_name;
private final int location_stages;
private final ArrayList <String> location_stage_descriptions;
public Locations(int location_id,
String location_name,
String location_description,
ArrayList <Integer> location_characters,
ArrayList <Integer> location_items,
ArrayList <Integer> location_enter_from,
ArrayList <Integer> location_exit_to,
String location_stage_name,
int location_stages,
ArrayList <String> location_stage_descriptions) {
this.location_id = location_id;
this.location_name = location_name;
this.location_description = location_description;
this.location_characters = location_characters;
this.location_items = location_items;
this.location_enter_from = location_enter_from;
this.location_exit_to = location_exit_to;
this.location_stages = location_stages;
this.location_stage_descriptions = location_stage_descriptions;
}
... below are getters/setters....
Public static class for the loader:
public static ArrayList <Locations> load_locations() {
//These are used for parsing the text file
String line;
ArrayList <String> lines = new ArrayList<>();
//These are used to initialize local variables
int location_id = 0;
String location_name = null;
String location_description = null;
ArrayList<Integer> location_characters = new ArrayList<>();
ArrayList<Integer> location_items = new ArrayList<>();
ArrayList<Integer> location_enter_from = new ArrayList<>();
ArrayList<Integer> location_exit_to = new ArrayList<>();
String location_stage_name = null;
int location_stages = 0;
ArrayList<String> location_stage_descriptions = new ArrayList<>();
//This is used to initialize ArrayList of objects
ArrayList <Locations> location_list = new ArrayList<>();
//here goes the code for parsing the text files....
//below is a sample portion that loads i.e 2,3,4 split into ints,
//into the ArrayList location_characters....
case "location_characters":
String[] characters = values[1].split(",");
for (String character : characters) {
location_characters.add(Integer.parseInt(character));
}
i++;
break;
//continued...
//below I am passing the parameters into constructor,
//then adding the object to ArrayList location_list
}
Locations location = new Locations(location_id,
location_name,
location_description,
location_characters,
location_items,
location_enter_from,
location_exit_to,
location_stage_name,
location_stages,
location_stage_descriptions);
location_list.add(location);
i = 0;
}
}
reader.close();
}
catch (IOException e){
System.out.println("Problem reading file.");
}
return location_list;
}
I will appreciate insight and pointers to solution
Your code is incomplete, and the problem is in the code you're not showing: You're passing the same lists to all constructor calls, so all Locations objects are using the same lists for their fields.
This can be fixed by initializing Locations fields at their declarations, eg:
private List<Integer> location_characters = new ArrayList<>();
// repeat this pattern for all List fields
and not passing them lists through the constructor.
If you need to add to the list:
locationsInstance.getlocation_characters().add(foo);
I have array variable declared like this:
public class carshop {
int numofcars = 0;
int maxcars = 10;
ACar[] allCars;
private CarShop;
public CarShop() { //Car Constructor
maxcars = maxE;
allCars = new ACar[maxcars];
}
}
In my coding example, every time a user adds a new car (via string input), it will increase the numofcars by 1. I have tried changing the array type into a arraylist
ArrayList<ACar> allCars = new ArrayList<ACar>(Arrays.asList());
I changed the allCars = new ACar[maxcars]; line into this: allCars = ACar.add(maxcars);
However now eclipse is giving me errors saying "The method add(int) is undefined for the type ACar".
Can you tell me what I have done wrong? Sorry if I have explained this poorly.
ACar is an array so it doesn't have the add() method and you need to insert values by doing ACar[x] = value;
If you want to easily convert an array to a List you can just do:
List<ACar> carList = Arrays.asList(allCars);
or for ArrayList specifically:
ArrayList<ACar> carList = new ArrayList<ACar>(Arrays.asList(allCars));
However you should also think about why you have both an array and an ArrayList. You could instead just be doing:
List<ACar> carList = new ArrayList<ACar>(maxCars);
The maxCars variable is optional, you don't need to set the initial size of an ArrayList unless you are trying to optimise the code.
Reading the first answer in the Passing a String by Reference in Java? I (as on old pointer freaked C nerd) have a question regarding using arrays as pointers in java.
I have a variably number of EditText boxes in a setup routine for a n number of strings to be stored. This includes a add one EditText box button. So on screen the button is followed by a n number of EditText boxes. I have a similar for URLs to be stored.
Instead of having the same like 20 lines of code repeated over and over again for different such setup data items it is quite obviously a case for a method (function in C) and the issue is how do I keep the information about what EditText boxes are created when the user is pushing the Save button. In C you just send a pointer of an array of editboxes and realloc the editboxes array if new editboxes are created. In Java I can't realloc a the editboxes array to expand it but can create and clone it. But then it is not the same the editboxes array. But then I have the old editboxes array in the calling method and not the new. But obviously with Strings it is possible to make a String array array of one unit and send to the method and get it updated. This is obviously possible to be used with editboxes arrays as well, making an editboxes array array of one editboxes array that could be updated by the called method and expanded.
String[][] stringList = new String[1][];
stringList[0] = new String[2];
stringList[0][0] = new String("Sonny");
stringList[0][1] = new String("Ronny");
ExpandArray(context, stringList);
public static void ExpandArray(Context context, String[][] stringPtr) {
stringPtr[0][1]="Zeke";
String[] strings = new String[3];
System.arraycopy(stringPtr[0], 0, strings, 0, stringPtr[0].length);
stringPtr[0] = strings;
stringPtr[0][2]="Sue";
}
and
EditText[][] EditTextList = new EditText[1][];
EditTextList[0] = new EditText[2];
EditTextList[0][0] = new EditText(context);
EditTextList[0][1] = new EditText(context);
ExpandArray(context, EditTextList);
public static void ExpandArray(Context context, EditText[][] EditTextPtr) {
EditText[] EditTexts = new EditText[3];
System.arraycopy(EditTextPtr[0], 0, EditTexts, 0, EditTextPtr[0].length);
EditTextPtr[0] = EditTexts;
EditTextPtr[0][2]== new EditText(context);
}
Question 1 Reading the first answer in the Passing a String by Reference in Java? all comments are in strong favour of the two first StringBuilder solutions, but with no explanation why. That is Strings here we are talking about class arrays, might be different. *I feel I just made a C-solution in Java syntax and there might be some better Java culture solutions? You know C nerds are crazy about pointers to pointers etc and this smells such. *
Are there any better solutions for class arrays than arrays (solution 3)?
I am learning Java culture and my actual method of a button and n number of EditText boxes (works fine), but feel like garage culture:
public static LinearLayout TextListbox(Context context, EditText[][] EditTextboxes, String Title, String DataStringsDimension) {
final Context contextTextListbox = context;
final EditText[][] EditboxTextListbox=EditTextboxes;
final String ItemText = Title;
final LinearLayout layoutEditTextListbox = new LinearLayout(contextTextListbox);
layoutEditTextListbox.setOrientation(LinearLayout.VERTICAL);
layoutEditTextListbox.setX(layoutEditTextListbox.getX() + 15);
layoutEditTextListbox.setBackgroundColor(Color.rgb(0xFF, 0xE8, 0xAA));
if (DataStringsDimension != null)
EditboxTextListbox[0] = new EditText[getJniListDataSize(DataStringsDimension)];
else
EditboxTextListbox[0] = new EditText[0];
final Button button = new Button(contextTextListbox);
button.setText("+ " + ItemText);
button.setTag(EditboxTextListbox[0].length);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Enlarge to Edit box array
EditText[] EditboxArrayTemp = new EditText[EditboxTextListbox[0].length + 1];
System.arraycopy(EditboxTextListbox[0], 0, EditboxArrayTemp, 0, EditboxTextListbox[0].length);
EditboxTextListbox[0] = EditboxArrayTemp;
// Register a new edit box
EditboxTextListbox[0][EditboxTextListbox[0].length - 1] = new EditText(contextTextListbox);
EditboxTextListbox[0][EditboxTextListbox[0].length - 1].setHint(ItemText);
EditboxTextListbox[0][EditboxTextListbox[0].length - 1].setInputType(InputType.TYPE_CLASS_TEXT);
layoutEditTextListbox.addView(EditboxTextListbox[0][EditboxTextListbox[0].length - 1]);
}
});
layoutEditTextListbox.addView(button);
if (EditboxTextListbox[0].length > 0) {
String[] DataStrings = getJniTextUnceListData(DataStringsDimension);
for (int iSlotTitle = 0; iSlotTitle < EditboxTextListbox[0].length; iSlotTitle++) {
EditboxTextListbox[0][iSlotTitle] = new EditText(contextTextListbox);
EditboxTextListbox[0][iSlotTitle].setText(DataStrings[iSlotTitle]);
EditboxTextListbox[0][iSlotTitle].setTag(DataStrings[iSlotTitle]);
EditboxTextListbox[0][iSlotTitle].setHint(ItemText);
EditboxTextListbox[0][iSlotTitle].setInputType(InputType.TYPE_CLASS_TEXT);
layoutEditTextListbox.addView(EditboxTextListbox[0][iSlotTitle]);
}
}
return layoutEditTextListbox;
}
Question 2 It certainly be improved as Java culture? Any smart ideas?
I have it as a method in the SetupDlg class of mine, any reason to make such a thing its own class?
There might be some better ideas of how to make a setup edit for n number of text strings to be edited?
You can just use ArrayList instead of Array. Array has a fixed size, but ArrayList can grow easily. Equivalent to this:
String[][] stringList = new String[1][];
stringList[0] = new String[2];
stringList[0][0] = new String("Sonny");
stringList[0][1] = new String("Ronny");
ExpandArray(context, stringList);
public static void ExpandArray(Context context, String[][] stringPtr) {
stringPtr[0][1]="Zeke";
String[] strings = new String[3];
System.arraycopy(stringPtr[0], 0, strings, 0, stringPtr[0].length);
stringPtr[0] = strings;
stringPtr[0][2]="Sue";
}
will be:
List<List<String>> stringList = new ArrayList<List<String>>();
stringList.add(new ArrayList<String>());
stringList.get(0).add(new String("Sonny"));
stringList.get(0).add(new String("Ronny"));
ExpandArray(context, stringList);
//Instead of expand array
stringList.get(0).add(new String("Sue"));
For editText just use:
List<List<EditText>> editText = new ArrayList<List<EditText>>()
The size of ArrayList increases as required.
And about passing by reference, in java everything is passed by value. Only class objects are passed by reference. So only if you pass a class object and modify it, the change will be reflected outside the function.
For strings you can use string builders or String objects but if its only one string following works as well:
void main(){
string txt = "foo";
txt = addString(txt);
System.out.println(txt);
}
String addString(String txt)
{
txt += " bar";
}
The output will be : foo bar
Hope this helps!!
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
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);