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.
Related
I want to print a quiz to my GUI using my draw method which changes depending on how many times it is looped through, but the way I'm doing it does not print the String[] fruit to the screen. I assume because its not registering the loop I'm trying to make with the time value(?) but I can't figure out why.
public class Fruit {
private String[] fruit = {};
public void draw(Graphics2D g) {
int time = 0;
for (int i = 0; i < fruit.length; i++) {
g.drawString(fruit[i], 100, 100);
}
if(time == 0){
String[] fruit = {
"Apples",
"Pears"
};
}
else if(time == 1){
String[] fruit = {
"Bananas",
"Kiwi"
};
}
time++;
}
}
There's at least two things wrong with that code.
You redeclare the name 'fruit' in two different local scopes, neither of which has anything to do with the member variable named 'fruit'. The member 'fruit' will never change from the empty array it was initialized to. Possibly you just mean 'fruit = ...' rather than 'String[] fruit = ...'.
You set local variable 'time = 0' at the top of the draw() method, and there's nothing to change it. Therefore at the point you test whether it's 0 or 1, it's always 0.
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.
This question already has an answer here:
Java Sorting Date field
(1 answer)
Closed 4 years ago.
This is a noob question, sorry, but I am totally confused.
I had created a class called CalendarItems.
The fields are:
int index
String description
String textdate
int daysaway
The constructor uses the first three fields. And for the moment I have created four objects within the class.
I now want to do two things:
Loop through the CalendarItem's
For each CalendarItem calculate daysaway, which is the difference between the text date and today. I have figured out how to calculate this and can manually add do it by calling my method for item1, then for item2, etc
But i'd like to understand how i can do this with a loop. If i was in javascript i'd have an multi-dimensional array and could easy create a loop to cycle through it, but in the scary new world of java I am lost
Sort my CalendarItems on the daysaway field
I want to do this so that I can display them as CardViews in order of soonest-first.
[Inflating CardViews has proved blissfully straight-forward, and I can (again, with a manual 'loop') inflate a card for each CalendarItem and add the various fields to it. And creating the class and fields and adding my 4 sample objects has also worked, so it hasn't been a total lost weekend.]
I think where I am going wrong is that I keep thinking in terms of multi-dimensional arrays from my experience with javascript and Excel VBA, and however much I read about objects and iterator interfaces and arraylists in java, my brain is just refusing to take it in.
I have Google'd a lot on this, but every 'simple guide to iterators' has left me more confused than when I started.
Thanks in advance to anyone patient enough to help me.
I post my solution, as I already wrote it, it should be a complete one:
public class CalendarItem implements Comparable<CalendarItem> {
private int index;
private String description;
private ZonedDateTime textdate;
private long daysAway = 0;
public CalendarItem(int index, String description, ZonedDateTime textdate) {
this.index = index;
this.description = description;
this.textdate = textdate;
this.calculateDaysAway();
}
private void calculateDaysAway() {
this.daysAway = ChronoUnit.DAYS.between(textdate, ZonedDateTime.now(ZoneId.systemDefault()));
}
public long getDaysAway() {
return daysAway;
}
#Override
public int compareTo(CalendarItem o) {
if (this.daysAway < o.daysAway) {
return -1;
} else if (this.daysAway > o.daysAway) {
return 1;
} else {
return 0;
}
}
public static void main(String[] args) {
CalendarItem c1 =
new CalendarItem(0, "One", ZonedDateTime.of(2018, 5, 21, 0, 0, 0, 0, ZoneId.systemDefault()));
CalendarItem c2 =
new CalendarItem(0, "Two", ZonedDateTime.of(2018, 5, 4, 0, 0, 0, 0, ZoneId.systemDefault()));
CalendarItem c3 =
new CalendarItem(0, "Three",ZonedDateTime.of(2018, 5, 11, 0, 0, 0, 0, ZoneId.systemDefault()));
CalendarItem c4 =
new CalendarItem(0, "Four", ZonedDateTime.of(2018, 5, 1, 0, 0, 0, 0, ZoneId.systemDefault()));
List<CalendarItem> calendarItems = new ArrayList<>(Arrays.asList(c1, c2, c3, c4));
Collections.sort(calendarItems);
for (CalendarItem item : calendarItems) {
System.out.println("Item " + item.getDescription() + " is " + item.getDaysAway() + " days away.");
}
}
}
Note: I am using ZonedDateTime from java 8 to represent the date.
For 1) you can either create array in java or you can use ArrayList and store your objects in that arraylist and iterate over arraylist.
ArrayList<CalendarItem> list = new ArrayList();
list.add(obj1); // obj1 is the instance you created for the calendar item.
for(CalendarItem c: list){
// this is loop , do whatever you want here
}
For sorting, Either write a comparator class or implement comparable interface to your CalenderItem and override method compareTo. In this method you can provide comparison logic based on requirede field.
For (1), what have you tried? If you need a multi-dimensional array, nothing stops you from using one. Consider:
int dim1 = 5;
int dim2 = 10; // whatever you need
CalendarItem[][] items = new CalendarItem[dim1][dim2];
Im this case you would iterate your array the same way as with JavaScript.
for (int i = 0; i < dim1; i++) {
for (int j = 0; j < dim2; j++) {
// do whatever you need to do
}
}
You can also read about the enhanced for loop if you don't actually need a numerical index.
For (2) have a look at the Comparator interface in the javadocs as well as the methods in the Collections class, in particolar the sort method.
I need to pre-populate a List with a large number of integer values.
Is there are faster way to do this other than iteration?
Current Code:
class VlanManager {
Queue<Integer> queue = Lists.newLinkedList();
public VlanManager(){
for (int i = 1; i < 4094; i++) {
queue.add(i);
}
}
This code is in the constructor of a class that is created pretty frequently so I'd like this to be as efficient (read:performance not lines of code) as possible
4094 isnt to many items to loop but if it is getting called very frequently you might look at doing something with a static variable.
private static Integer[] theList;
static {
theList = new Integer[4094];
for (int i = 1; i < 4094; i++) {
theList[i-1] = i;
}
}
then make that list a List
Queue<Integer> intQue = new LinkedList(Arrays.asList(theList));
There is a danger of using this method if you have a list of mutable objects. Heres an example of what can happen. Integers are immutable so this doesnt actually apply to your question as it stands
class MyMutableObject {
public int theValue;
}
class Test {
private static MyMutableObject[] theList;
static {
theList = new MyMutableObject[4094];
for (int i = 1; i <= 4094; i++) {
theList[i-1] = new MyMutableObject();
theList[i-1].theValue = i;
}
}
public static void main(String [] args) {
Queue<MyMutableObject> que = new LinkedList(Arrays.asList(theList));
System.out.println(que.peek().theValue); // 1
// your actually modifing the same object as the one in your static list
que.peek().theValue = -100;
Queue<MyMutableObject> que2 = new LinkedList(Arrays.asList(theList));
System.out.println(que2.peek().theValue); // -100
}
}
#Bohemian Has some good points on using a static List instead of an array, while the performance gains are very small they are none the less performance gains. Also because the 'array' is actually only ever being used as a List not an array it should be declared as such.
private static List<Integer> theList;
static {
theList = new ArrayList(4094);
for (Integer i = 0; i < 4094; i++) {
theList.add(i+1);
}
}
The fastest way would be to create a reference list (initialized using an instance block - neatly wrapping it all up in one statement):
private static final List<Integer> LIST = new ArrayList<Integer>(4094) {{
for (int i = 1; i < 4094; i++)
LIST.add(i);
}};
Then in your constructor, initialize the queue using the copy constructor:
Queue<Integer> queue;
public VlanManager(){
queue = new LinkedList<Integer>(LIST);
}
You will not write a faster implementation than what's in the JDK.
I realize this question has already been answered. But I think one important answer is missing: The fastest way to initialize a LinkedList with the values 0..4093 is .. DON'T DO IT AT ALL. Especially if speed is an issue.
What you basically are doing is creating a structure consisting of 4093 Node elements each consiting of two pointers to prev/next element and one pointer to an Integer object. Each of this Nodes must be created (and free). In addition nearly each contained Integer must be created (and freed). 'Nearly' because Java uses a cache for Integer but normally (you can change this with system properties) in the range of -127..127.
This is a lot to do in order to get a simple list of integer and if used intensively gives the GC a lot to do afterwards.
That being said there are numerous possible ways of doing this in a more efficient way. But they depend on what your concrete usage pattern is. Just to name a few:
Use an Array: boolean [] inUse' and set the taken vlan-id totrue` if it's taken
Even better use a BitSet instead of the array
Don't store which vlan is free, but which vlan is taken. I think they tend to be free and so there are much more free as there are taken ones. (this means much less to keep track of).
If you insist on using a LinkedList don't initialize it with your class but have it already initialized. This depends on how much of them you would need. You could keep a pool of them. Or perhaps your codes allows reusage of old lists. (yes, you could sort them after usage.)
Surely there are more...
All of this methods require you to build your own 'Queue' interface. But perhaps this has not to be as rich as Java's. And it really isn't that difficult. If you really use this intensively you could reach perfomance improvement factor 10x-1000x++.
A possible implementation using BitSet with an instantiation cost of nearly nothing could be:
import java.util.BitSet;
import org.testng.annotations.Test;
public class BitSetQueue {
// Represents the values 0..size-1
private final BitSet bitset;
private final int size;
private int current = 0;
private int taken = 0;
public BitSetQueue( int size ){
this.bitset = new BitSet( size );
this.size = size;
this.current = size-1;
}
public int poll(){
// prevent endless loop
if( taken == size ) return -1;
// seek for next free value.
// can be changed according to policy
while( true ){
current = (current+1)%size;
if( ! bitset.get( current ) ){
bitset.set( current );
taken++;
return current;
}
}
}
public boolean free( int num ){
if( bitset.get( num ) ){
bitset.clear( num );
taken--;
return true;
}
return false;
}
#Test
public static void usage(){
BitSetQueue q = new BitSetQueue( 4094 );
for( int i = 0; i < 4094; i++ ){
assertEquals( q.poll(), i );
}
assertEquals( q.poll(), -1 ); // No more available
assertTrue( q.free( 20 ) );
assertTrue( q.free( 51 ) );
assertEquals( q.poll(), 20 );
assertEquals( q.poll(), 51 );
}
}
I'm new to using OOP, I typically just put all my code in a single class and use methods. But I want to maintain state information and think classes are the best fit but I'm having trouble wrapping my head around it.
Say I have a list of items and I want to stop when the total sum of all previous items in the list equals X(in this case 10 so it takes item 1 + 2, then 2+3.etc..until it hits the threshold 10), I can use a method to calculate it but it involves me doing the entire process all over again when all I really need to do is increment by the last item and then see if my data exceeds the threshold. Here's my code so far but I know its not good because although it works its really just using the class as an independent method and recalculating on every loop. My goal is to,using this structure, reduce loops if not necessary to check thresholds.
Any suggestions?
Code:
public class LearningClassesCounter {
public static void main(String[] args) {
int[] list = new int[]{1,2,3,4,5,6,7,8,9,10};
int[] data_list = new int[list.length];
for (int current_location = 0; current_location<list.length;current_location++) {
//can only put commands in here. Nothing above.
Counter checker = new Counter(data_list);
System.out.println(checker.check_data(current_location));
for (int i =0; i<100; i++){
if (checker.check_data(current_location) == false) {
break;
}
data_list[current_location] = (list[current_location]+1); //this is just a random function, it could be any math function I just put it in here to show that some work is being done.
}
}
//its done now lets print the results
for (Integer item : data_list) {
System.out.println(item);
}
}
}
class Counter {
private int[] data_list;
private int total_so_far;
// create a new counter with the given parameters
public Counter(int[] data_list) {
this.data_list = data_list;
this.total_so_far = 0;
}
public boolean check_data(int current_location) {
// TODO Auto-generated method stub
int total_so_far = 0;
//System.out.println(total_so_far);
for (int item : data_list) {
total_so_far = item + total_so_far;
if (total_so_far >= 10) {
break;
}
}
if (total_so_far>=10) {
return false;
} else {
return true;
}
}
}
I don't need anyone to fix my code or anything(I want to do it myself, the code is just to give an idea of what I'm doing). I'm more interested in the flaw in my logic and maybe a way for me to better think about designing classes so I can apply them to my own situations better.
So the solution is that you do not update the data_list directly. Instead have a setter method in the Counter class that takes the index and value to update. It updates the value in the array and also updates a count value.
Something like this:
class Counter{
private final int[] list;
private count = 0;
private final maxCount = 10;
public Counter(int[] list){
this.list = list;
}
public boolean updateValueAndCheckPastMax(int index, int value){
list[index] = value;
count += value;
return count >= maxCount;
}
}
You are way over thinking this, and a counter class is not really necessary in this case.
I'm also interested as to why you'd be doing this line:
data_list[current_location] = (list[current_location]+1);
Do you want your data_list to be the same as list, but each value is incremented by 1?
If you are merely trying to return a sub-array of the values that are < 10, i would suggest just doing this in a for loop, and using an int as a counter.