I have created an object ArrayList,
private ArrayList<Object> objects;
and I am initializing it in a constructor.
public ObjectManager(Handler handler) {
this.handler = handler;
objects = new ArrayList<>();
}
This ArrayList is then painted/added it to a canvas.
public void renderObjects(Graphics g) {
handler.getObjectManager().addObject(new InstanceOfObject(handler, 1000, 1000, g));
}
The method addObject(), adds an object to the ArrayList.
public void addObject(Object e) {
objects.add(e);
}
I would like to remove this object later, by using a similar line of code,
public void removeObject(Object e) {
objects.remove(e);
}
however I do not know how to do that because I do not know how to pass in the object that is being removed. The only way I can think of passing in the object is by doing the following:
handler.getObjectManager().removeObject(new InstanceOfObject(handler, 1000, 1000, g));
I don't even know if this would work because it's removing an "new" object. And even if it does, "g" is not defined. If I define it in the constructor, I have to change many different things which results in an error (usually a NullPointerException), but even then I cannot figure out how to call this method by passing in the Graphics g parameters.
Your Question is not clear, but this might help.
The List interface implemented by ArrayList already offers a remove method. No need for you to re-invent that.
Object reference
To remove an object, keep and pass a reference to the particular object.
Dog alice = new Dog( "Alice" , "Labrador" ) ;
Dog bob = new Dog( "Bob" , "Chihuahua" ) ;
List< Dog > dogs = new ArrayList<>() ;
dogs.add( alice ) ;
dogs.add( bob ) ;
…
dogs.remove( bob ) ;
Index number
Alternatively, remember the slot (index) of the list containing the object you want to remove. Pass that zero-based index number to the remove method.
You can actually find Java's source code on the web (like https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/share/classes/java/util/ArrayList.java#L644), or even as src.zip in the JDK itself. So this is how remove() looks like:
public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
int i = 0;
found: {
if (o == null) {
for (; i < size; i++)
if (es[i] == null)
break found;
} else {
for (; i < size; i++)
if (o.equals(es[i]))
break found;
}
return false;
}
fastRemove(es, i);
return true;
}
and while the loops with the labeled breaks may look a bit esoteric, the important part is the o.equals(): if your "InstanceOfObject" class implements its own equals(), you can make the comparison work with freshly made throwaway instances too.
Related
My current goal here is to add objects to a vector in order to be accessed by an iterator in another class created by me (for this project I am not allowed to use Java's iterator). My iterator function is supposed to return a specific object inside the vector. Instead, the iterator is reporting null values within the vector. After debugging, the problem is after objects are added on startup the objects disappear. Passing the vector into the iterator class doesn't solve the issue. I've tried using an array list instead of a vector with no luck.
public void init() { //where im doing the adding
for (int i = 0; i < 1; i++) {
cyborg = new Player(ColorUtil.rgb(42, 194, 225), 50, 46.0, baseLocations[0], 40, 100, 100, 0, 50, true);
go.add((Player) cyborg);
}
for (int i = 0; i < 3; i++) {
NPC = new NPC(ColorUtil.rgb(42, 194, 225), 50, 46.0, baseLocations[0], 40, 100, 100, 0, 50, currStrat);
go.add((NPC) NPC);
}
for (int i = 0; i < 2; i++) {
drone = new Drone(ColorUtil.rgb(82, 95, 81), r.nextInt(50), 10.0,
new Point(r.nextFloat() * 1000, r.nextFloat() * 1000), r.nextInt(50));
go.add(drone);
}
for (int i = 0; i < 4; i++) {
base = new Base(ColorUtil.rgb(169, 235, 0), baseSequence++, baseLocations[i], 10);
go.add((Fixed) base);
}
for (int i = 0; i < 2; i++) {
eStation = new eStation(ColorUtil.rgb(100, 85, 85), new Point(r.nextFloat() * 1000, r.nextFloat() * 1000),
r.nextInt(50), 100);
go.add((Fixed) eStation);
}
public class GameCollection implements ICollection {
private Vector<GameObject> gameCollection;
public GameCollection() {
gameCollection = new Vector<GameObject>(); //the vector im having problems with
System.out.println(gameCollection.toString()); //Test to check if objects in game collection array. Prints null values after startup
}
public IIterator getIterator() {
GameCollectionIterator gameItr = new GameCollectionIterator(gameCollection);
return gameItr;
}
public void add(GameObject o) {
gameCollection.addElement(o);
//System.out.println(super.toString());
}
public Object elementAt(int location) {
if(location < gameCollection.size()) {
return (Object) gameCollection.indexOf(location);
}
throw new ArrayIndexOutOfBoundsException(location);
}
public void remove(GameObject o) {
// TODO Auto-generated method stub
gameCollection.remove(gameCollection.indexOf(o));
}
private class GameCollectionIterator implements IIterator{
private int currIndex = 0;
private Vector <GameObject> game = new Vector <GameObject>();
public GameCollectionIterator(Vector<GameObject> g) {
game = g;
}
#Override
public boolean hasNext() {
if(game.size() <= 0){
System.out.println("First case");
return false;
}
if(currIndex == game.size() -1){
System.out.println("Second case");
return false;
}
return true;
}
#Override
public Object getNext() {
currIndex++;
return(game.indexOf(currIndex));
}
#Override
public void remove() {
game.remove(currIndex);
}
}
I can see a few problems with your iterator here:
#Override
public Object getNext() {
currIndex++; // (1)
return(game.indexOf(currIndex)); // (2)
}
currIndex++; - you increment index before getting the element from the vector, so you basically always skip the first element (with index 0).
game.indexOf(currIndex) - indexOf returns the index of the first occurrence of the specified element, see the doc. You have to use get method instead, see the doc.
First of all, we can't actually see what is going on because you haven't provided an kind of "driver" so that we can understand how these classes are being used.
However, I suspect that the problem is that your GameCollectionIterator is incorrect. It has a number of problems, including:
The next method is assuming that there is a next element. It is not checking. (OK, we don't know what the IIterator contract says should happen, but this is very suspicious.)
As #rxn1d also notes, next increments currIndex (which starts as zero) before using it. That means that the iterator will skip the first element under most circumstances.
#rxn1d is also correct about return(game.indexOf(currIndex));. That statement will actually:
autobox currIndex to an Integer
attempt to find the Integer in the list,
fail ... giving the int value -1, and
autobox and return that1.
There is nothing in the iterator implementation to detect the case of elements being added or removed while iterating. When you remove any object, the remaining objects beyond the removal point will have their positions changed. But you are not adjusting currIndex for this. Thus a removal is liable to cause objects to be skipped.
The iterator will not be thread-safe. (Not clear if this matters ...)
Note that the standard (non-concurrent) implementations of java.util.Collection will detect a concurrent modification and throw an exception precisely to avoid problems like 4.
Some other things that should be corrected.
You should get rid of superfluous blank lines and autogenerated comments2 before you as other people to read your code.
I don't understand why you are using your own IIterator and ICollection interfaces ... or what they actually mean. (Where are the declarations? Where are the javadocs?)
Your throw new ArrayIndexOutOfBoundsException(location); is throwing the wrong exception. Your collection is not an array.
eStation is a bad class name. Class names shout always start with an uppercase letter. Then you compound this by declaring a variable with exactly the same name as its class.
Assuming that eStation is a subtype of GameObject, the type cast in go.add((Fixed) eStation); is unnecessary. Other examples of this.
1 - I am surprised that you did not notice that next was returning Integer objects. Or if you did, that you didn't think it was significant enough to mention.
2 - You should always do this before showing your code to other people and ask them to read it. Treat us like you would treat your future co-workers.
I am eventually fetching objects from my backend and I have to keep track of them. I need a collection where there are no duplicates, but every time I fetch the same object from the backend I get a new instance, so I must compare it's String key manually, I suppose.
Plus, these objects need a boolean associated with them, because they may be in this list and be "used" and I should know that later.
A typical scenario is that I have a list of 10 objecst in my collection and I fetch 8 new ones, and only 3 are new. I should add these 3 to these list and discard the 5 repeated ones.
I am about to start implementing a custom Collection for that. Is there any possibility to do it combining Pair with List, or maybe HashMap? I've been thinking on this and I couldn't come up with a conclusion.
http://docs.oracle.com/javase/7/docs/api/java/util/Set.html#add(E) Try something with a set. It allows no duplicates.
In the class of your objects, override both equals() and hashCode() to specify when two instances of your class can be considered to be the same.
If you do this, you can simply throw them into a HashSet and it will make sure that no to elements in it are the same (by the definition that you provided in the overridden methods)
Take a look at this similar question:
Implement equals with Set
For future reference, I implemented a custom class with both a list of objects and an array with my booleans. Since I had to keep both list and array synchronized, I had to iterate this list on all steps.
This is my code:
public class PromoCollection {
public static List<ParseObject> promotions = new ArrayList<ParseObject>();
public static List<Boolean> isTriggered = new ArrayList<Boolean>();
public static void add(ParseObject newObj) {
for (ParseObject p : promotions) {
if (p.getObjectId().equals(newObj.getObjectId())) {
return; // Object already in list, do not add
}
}
promotions.add(newObj); // Add new object
isTriggered.add(false); // And respective boolean
}
public static void remove(ParseObject obj) {
for (int i = 0; i < promotions.size(); ++i) {
if (obj.getObjectId().equals(promotions.get(i).getObjectId())) {
promotions.remove(i);
isTriggered.remove(i);
return;
}
}
}
public static void trigger(ParseObject obj) {
for (int i = 0; i < promotions.size(); ++i) {
if (obj.getObjectId().equals(promotions.get(i).getObjectId())) {
isTriggered.set(i, true);
}
}
}
public static boolean isTriggered(ParseObject obj) {
for (int i = 0; i < promotions.size(); ++i) {
if (obj.getObjectId().equals(promotions.get(i).getObjectId())) {
return isTriggered.get(i);
}
}
throw new ArrayStoreException();
}
}
Ok so I'm doing an assignment for my java coursets part I'm stuck at is :
"Implement an operation createparliamentMembers which will create the particular Parliament
with 80 members."
So i've already created the constructor with it's methods. This is how I wrote the operation to create the objects using the constructor.:
public static void createparliamentMembers(){
Member[] array = new Member[75];
for(int i = 0; i < array.length; i++)
{
if (i < 35) array[i] = new Member(i, "Blue");
else array[i] = new Member(i,"Red");
}
Legislator[] leg = new Legislator[3];
for (int i = 0 ; i < leg.length; i++){
leg[i] = new Legislator(i, "Impartial");
}
Leader[] lead = new Leader[2];
for (int t = 0; t < lead.length; t++){
if (t < 1) lead[t] = new Leader(1, "Red");
else lead[t] = new Leader(2, "Blue");
}
The problem is the arrays and objects only seem to exist in the operation for creating them and when I try running method of the objects created they don't work because the driver class doesn't recognize the arrays. On the other hand when I use this as just a normal part of the Driver for it runs fine and all methods of the objects work normally.
Edit: Ok so I'm still getting the same problem as before even though i initiliased them outside the createparliamentMembers();
The following code is the Driver im using to test the methods: It keeps saying there is a:
Exception in thread "main" java.lang.NullPointerException at Driver.main(Driver.java:11)
which is the code array[1].FlipCoin(); as im trying to use the method flipcoin from the created objects but it's not working.
public static void main(String [] args) {
Commands.createparliamentMembers();
array[1].FlipCoin();
}
Your arrays are only defined locally, which means they live and die with the method. When your method finishes, they get put out of memory.
The solution is to define these arrays as instance variables. By that I mean, you need to define the arrays for your class, and then use them in your method:
class someClass {
int[] myArray = new int[2];
private void someMethod() {
myArray[0] = 3;
myArray[1] = //whatever
}
}
You state in comment:
I do have a parliament class it's on it own and contains the methods and constructor for the members of the parliament. The above method was in a seprate class called Commands. I don't understand completely the "Can you add the members to a Parliament object as you create them?" The parliament isn't an object more se then a class containing a constructor and methods for parliament members i want to create.
Parliament isn't an object yet, but you should in fact create one, and in fact your instructions tell you just that: "which will create the particular Parliament with 80 members...". You will need to tell us more about your program's structure and your specific requirements, but I suggest:
First create a Parliament object in the createParliamentMembers method, and call it parliament.
Then create the members of parliament in that method.
As you create these members, add them to the Parliament object, parliament.
At the end of the method return the parliament variable.
This means that your createParliamentMembers method's signature must change so that rather than return void it should be written to return a Parliament object.
When calling the method in the main method, assign what it returns to a Parliament variable that is in the main method.
It looks like you are writing a factory method. Create a constructor for Parliament like this:
public Parliament(Member[] members, Legislator[] legislators, Leader[] leaders) {
// do whatever with what's passed in
}
Then change your method to return a Parliament object and in the method pass your initialized arrays into the Parliament constructor, like this:
// same code as your except the last line
public static Parliament createParliament(){
Member[] array = new Member[75];
for(int i = 0; i < array.length; i++)
{
if (i < 35) array[i] = new Member(i, "Blue");
else array[i] = new Member(i,"Red");
}
Legislator[] leg = new Legislator[3];
for (int i = 0 ; i < leg.length; i++){
leg[i] = new Legislator(i, "Impartial");
}
Leader[] lead = new Leader[2];
for (int t = 0; t < lead.length; t++){
if (t < 1) lead[t] = new Leader(1, "Red");
else lead[t] = new Leader(2, "Blue");
}
return new Parliament(array, leg, lead);
}
Sorry, the title is not very understandable, but my English is not helping. I am a new programmer in java, and despite having read how parameters work, I do not really understand what is happening.
sudokuBoard alter = new sudokuBoard();
this.createRandomSudokuBoard();
alter.setBoardFromArray(this.getBoard().clone());
(...)
for(int i = 0; i < 81; i++) {
alter.clearCell(positionListonX[i], positionListonY[i]); <<<<<<<<<<<<< Here
if(alter.numberOfSolutions(2) < 2) {
this.clearCell(positionListonX[i], positionListonY[i]);
alter.setBoardFromArray(this.getBoard().clone());
} else {
alter.setBoardFromArray(this.getBoard().clone());
}
}
What happens is that in the indicated line, calling the method clearCell of the object alter is also modifying the current object (this). In a last desperate attempt, I tried to resolve it with the clone() method (as you can see), but it did not work.
What's going on? What am I missing? thank you very much.
If you haven't implemented clone() in SudokuBoard, then you're probably getting the default clone() defined on Object, which doesn't perform a deep copy of the object. See Deep Copy for an explanation. If you actually want a completely separate instance of your board in alter, you will need to do something like this:
class SudokuBoard
{
public void setBoard( SudokuBoard other )
{
for( int i = 0; i < 81; i++ )
{
this.positionListonX[i] = other.positionListonX[i];
this.positionListonY[i] = other.positionListonY[i];
}
// Copy any other properties
}
}
Note that if the values in your positionListonX and positionListonY arrays are not primitive types, you'll also need deep copies of those. This is effectively a copy constructor, but I didn't give it that signature (public SudokuBoard( SudokuBoard other)) because I don't know the rest of the internals of SudokuBoard.
It would help to see more of the method signatures defined in your SudokuBoard class, so we know what methods are available and can understand what they do.
Edit
class SudokuBoard
{
public void setBoardFromArray( int[][] otherBoard )
{
for( int i = 0; i < otherBoard.length; i++ )
{
// Clone the arrays that actually have the data
this.board[i] = otherBoard[i].clone();
}
}
}
I would like to create an initialisation method for a Java class that accepts 3 parameters:
Employee[] method( String[] employeeNames, Integer[] employeeAges, float[] employeeSalaries )
{
Employee myEmployees[] = new Employee[SIZE]; // I don't know what size is
for ( int count = 0; count < SIZE; count++)
{
myEmployees[count] = new Employee( employeeNames[count], employeeAges[count], employeeSalaries[count] );
}
return myEmployees;
}
You may notice that this code is wrong. The SIZE variable is not defined. My problem is that I would like to pass in 3 arrays, but I would like to know if I can ensure that the three arrays are ALL of the same array size. This way the for loop will not fail, as the constructor in the for loop uses all the parameters of the arrays.
Perhaps Java has a different feature that can enforce a solution to my problem. I could accept another parameter called SIZE which will be used in the for loop, but that doesn't solve my problem if parameters 1 and 2 are of size 10 and the 3rd parameter is an array of size 9.
How can I enforce that the 3 arguments are all arrays that contain the exact same number of elements? Using an extra parameter that specifies the array sizes isn't very elegant and kind of dirty. It also doesn't solve the problem the array parameters contain different sized arrays.
You can't enforce that at compile-time. You basically have to check it at execution time, and throw an exception if the constraint isn't met:
Employee[] method(String[] employeeNames,
Integer[] employeeAges,
float[] employeeSalaries)
{
if (employeeNames == null
|| employeeAges == null
|| employeeSalaries == null)
{
throw new NullPointerException();
}
int size = employeeNames.length;
if (employeesAges.length != size || employeeSalaries.length != size)
{
throw new IllegalArgumentException
("Names/ages/salaries must be the same size");
}
...
}
Since the arrays being passed in aren't generated until runtime, it is not possible to prevent the method call from completing depending upon the characteristics of the array being passed in as a compile-time check.
As Jon Skeet has mentioned, the only way to indicate a problem is to throw an IllegalArgumentException or the like at runtime to stop the processing when the method is called with the wrong parameters.
In any case, the documentation should clearly note the expectations and the "contract" for using the method -- passing in of three arrays which have the same lengths. It would probably be a good idea to note this in the Javadocs for the method.
A way to skirt around the problem is to create a builder, e.g., EmployeeArrayBuilder,
public class EmployeeArrayBuilder {
private Integer arraySize = null;
private String[] employeeNames;
public EmployeeArrayBuilder addName(String[] employeeNames) {
if (arraySize == null) {
arraySize = employeeNames.length;
} else if (arraySize != employeeNames.length) {
throw new IllegalArgumentException("employeeNames needs to be " + arraySize + " in length");
}
this.employeeNames = employeeNames;
return this;
}
public EmployeeArrayBuilder addSalaries(float[] employeeSalaries) {/* similar to above */}
public EmployeeArrayBuilder addAges(Integer[] employeeAges) {/* similar */}
public Employee[] build() {
// here, you can do what you needed to do in the constructor in question, and be sure that the members are correctly sized.
Employee myEmployees[] = new Employee[arraySize ];// dont know what size is
for ( int count = 0; count < arraySize ; count++) {
myEmployees[count] = new Employee( employeeNames[count], employeeAges[count], employeeSalaries[count] );
}
return myEmployees;
}
}