Cannot find symbol in for loop - java

I am getting the error now that BookCollection.java:67: error: incompatible types
collection[lastElement++] = b;
Also am not sure if my constructor is set up correctly? The directions were:
Constructor:
Given a parameter specifying the limit on the collection size, an empty book collection is created using the given parameter. The parameter should not exceed the preset maximum size 200.
Am I initializing my variables correctly then? An answer below helped me change my code, but although I do not get errors within my constructor, I feel as though it may not be correct according to the directions....
I'll paste the couple chunks of my code that pertain to the question.
public class BookCollection{
//data fields, need complete
private int limit = 200;
//Array of type book
private int Book[];
//actual size of collection, initialized to zero. Must never exceed limit
private int collection[];
private int lastElement;
//Constructor
public BookCollection(int l, int c[], int le,int b[]){
Book = b;
collection = c;
limit = l;
lastElement = le;
int lastElement = 0;
if(limit <= 200){
Book[] collection = new Book[limit];
} else{
throw new UnsupportedOperationException("CannotExceedLimit");
}
}
ANNDDDD where I am getting the error:
public void addBook(int b[], int c[]) {
Book = b;
collection = c;
if (lastElement == collection.length) {
throw new UnsupportedOperationException("CorrectionFull");
}
for (int i = 0 ; i != lastElement ; i++) {
if(b.equals(collection[i])) {
throw new UnsupportedOperationException("DuplicateBook");
}
}
collection[lastElement++] = b;
}

You have not declared i as an integer in your for loop. So add the declaration with initialization. Replace this
for(i=0; i<collection.length; i++){
with
for(int i=0; i<collection.length; i++){

This statement
BookCollection[] collection = new BookCollection[limit]; //initialize array of 200
declares a local array. It gets destroyed as soon as you leave the constructor.
The collection that stays around is this one:
private int collection[];
It consists of ints, so when you try to do this
collection[i].add(b);
the compiler correctly complains that int does not have a method called add.
Good chances are, even declaring the collection as
private Book[] collection;
and initializing it in the constructor as
collection = new Book[limit];
is not going to help, though: unlike collections, Java arrays do not let you change their size dynamically, so you need to store an index of the last element of the collection[] array that has been set.
This leads to understanding that you need a loop for finding duplicates, and noting else: define an element int lastElement, set it to zero in the constructor, and rewrite the addBook method as follows:
public void addBook(Book b) {
if (lastElement == collection.length) {
throw new UnsupportedOperationException("CorrectionFull");
}
for (int i = 0 ; i != lastElement ; i++) {
if(b.equals(collection[i])) {
throw new UnsupportedOperationException("DuplicateBook");
}
}
collection[lastElement++] = b;
}

You did't declared i as a int type variable, make it as
for(int i=0; i<collection.length; i++){
^here
//...
}

Related

How to create an ensureCapacity method that deals with Array Generics in Java

So, I am creating a generic data structure named "Sack". In this I add items to a sack, grab a random item, see if it's empty, or dump out its contents etc. Also I'm creating it to expand to hold as many items as needed.
I am currently working on a ensureCapacity method which it should ensure that the sack has the capacity for its parameter value, and if not, create a new underlying data structure for the sack that is one more than twice the current capacity of the sack.
I've tried numerous of methods of doing this, but I keep receiving an error. I'll drop down most of my code, but also the two methods I've tried and pointing out the errors I receive.
public class Sack<E>
{
public static final int DEFAULT_CAPACITY = 10;
private E [] elementData;
private int size;
#SuppressWarnings("unchecked")
public Sack()
{
elementData = (E[]) new Object[DEFAULT_CAPACITY];
}
#SuppressWarnings("unchecked")
public Sack(int capacity)
{
if(capacity < 0)
{
throw new IllegalArgumentException("capacity " + capacity);
}
this.elementData = (E[]) new Object[capacity];
}
public boolean isEmpty()
{
if(size == 0)
{
return true;
}
else
{
return false;
}
}
public E [] dump()
{
E [] E2 = Arrays.copyOf(elementData, size);
for(int i = 0; i < size; i++)
{
elementData[i] = null;
}
size = 0;
return E2;
}
First One:
In this error, it's mainly when I run my tests saying that
AssertionFailedError: ensureCapacity is not working correctly
private void ensureCapacity(int capacity)
{
if (size != capacity)
{
int newCapacity = (capacity * 2) + 1;
elementData[capacity] = elementData[newCapacity];
}
}
A little update, I will posts my tests. You guys can check it out and let me know, however I cannot modify my tests at all. Only my code. I commented the first line since that's where my error occurs.
#Test
public void testEnsureCapacity()
{
assertEquals(2, ensureCapacity.getModifiers(), "ensureCapacity does not have the correct modifiers"); // My error occurs here currently.
try
{
for(int i=0; i<=10; ++i)
{
ensureCapacity.invoke(s, i);
assertEquals(10, ((Object[])elementData.get(s)).length, "ensureCapacity is not working correctly (capacity changing unnecessarily)");
}
ensureCapacity.invoke(s, 11);
assertEquals(21, ((Object[])elementData.get(s)).length, "ensureCapacity is not working correctly (capacity not increased correctly)");
Random rand = new Random();
int capacity = rand.nextInt(100)+1;
s = new Sack<Integer>(capacity);
for(int i=0; i<=capacity; ++i) {
ensureCapacity.invoke(s, i);
assertEquals(capacity, ((Object[])elementData.get(s)).length, "ensureCapacity is not working correctly (capacity changing unnecessarily)");
}
ensureCapacity.invoke(s, capacity+1);
assertEquals(capacity*2+1, ((Object[])elementData.get(s)).length, "ensureCapacity is not working correctly (capacity not increased correctly)");
} catch (Exception e) {
fail("ensureCapacity is not working correctly");
}
}
You're getting that error because of "Erasure" - ie. the generic types are for compile-time only, but are "erased" from the compiled byte-code. This means that the run-time does not know which type "E" represents, so cannot create instances of (nor arrays of) any generic type. (See also What is erasure ).
So, you can replace that error line to create an Object array as you have done already :
E [] newList = (E[]) new Object[DEFAULT_CAPACITY];
But that's not ideal - much better is to create the arrays of the correct type straight off. The workaround to do that is to modify your constructor to take an argument of the actual runtime type Class (I like calling this argument "clazz"), so you can keep that reference handy - so :
private Class<E> clazz;
#SuppressWarnings("unchecked")
public Sack(Class<E> clazz, int capacity)
{
if(capacity < 0)
{
throw new IllegalArgumentException("capacity " + capacity);
}
this.clazz = clazz;
this.elementData = (E[]) Array.newInstance(this.clazz, capacity);
}
and of course replace that error line with :
E [] newList = (E[]) Array.newInstance(this.clazz, capacity);
EDIT FOR "First" AND UNIT-TEST:
So in your unit-test - I assume "ensureCapacity" is a variable of type Method.
That assert states that it is expecting two modifiers, but the actual value it finds in one.
I expect you will have covered modifiers in your class, but briefly you can consider that there are two "groups" of modifiers - "Access-Modifiers" and the rest (ie "Non-Access-Modifiers") - see https://dzone.com/articles/all-about-java-modifier .
As I mentioned, you have one modifier already on your ensureCapacity method - namely, the Access-Modifier "public". So the assertion error that you're getting means that you are expected to have another (non-access) modifier alongside it. I can only guess which that second modifier would be (again, that would have been covered in your class), but it will be one of those in the dzone article above - so read that article, and compare it to what you have been taught.
So something like :
private void ensureCapacity(int capacity)
{
if (size > capacity)
{
int newCapacity = (capacity * 2) + 1;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
I figured it out, here's what the solution is to my question.
private void ensureCapacity(int capacity)
{
if (elementData.length < capacity)
{
int newCapacity = elementData.length * 2 + 1;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}

array required but [ClassName] found java

I'm trying to write a function checking if 2 arrays are equal.
public class DynamicArray {
private int size; // stores the number of “occupied” elements in the array
private int[] array;
...
boolean equals(DynamicArray obj) {
boolean keepChecking = true;
int objSize = 1;
for (int i = 0; i < obj.length; i++) {
if (obj[i] == 0 && keepChecking) {
keepChecking = false;
objSize = obj[i];
}
}
if (size != objSize)
return false;
for (int i = 0; i < size; i++) {
if (array [i] != obj [i]) {
return false;
}
}
return true;
}
}
The thing is that array might be partially filled array, not filled elements will be just zeros. So, to check if 2 arrays are equal, first, I find the size of the occupied array and then I do all the checkings.
So, every time I'm trying to get the value of obj[i] or obj.length it keeps showing the error "array required, but DynamicArray found." for obj[i] and "cannot find symbol \n symbol: variable length \n location: variable obj of type DynamicArray" which I don't understand because the other array is also DynamicArray type
public class ArrayDemo {
public static void main(String[] args) {
DynamicArray ar1 = new DynamicArray(1);
DynamicArray ar2 = new DynamicArray(1);
System.out.println("equals() is " + ar1.equals(ar2));
}
}
Your parameter obj in the equals method is not an array but an instance of DynamicArray. Therefore you cannot access the values with the [] on the identifier obj. You need to rewrite that method. You also need to include methods for setting and getting the elements of the array in your DynamicArray object. For example:
val = ar1.get(0);
and
ar1.set(0, value);
So this means your Dynamic array needs the following two methods (I am assuming the values of your array are ints, but this could be anything). I'll let you figure out what goes in them as I see you must be learning the language.
public void set(int index, int value){
}
public int get(int index){
}
That way you can then use your methods in your rewritten equals function to access the elements of the array.
Another tip. You would be better sorting both arrays. Compare the first element or each, then the next, and then the next until such time you find a mismatch. At that point you can return false. If you find no mismatch return true.
The thing is , DynamicArray is not an array, its a class, you have to define a length function of it.you can just call obj.length wich is DynamicArray class which has no method length

creating java generic data structure

I am building a data structure to learn more about java. I understand this program might be useless.
Here's what I want. I want to create a data structure that store smallest 3 values. if value is high, then ignore it. When storing values than I also want to put them in correct place so I don't have to sort them later. I can enter values by calling the add method.
so let's say I want to add 20, 10, 40, 30 than the result will be [10,20,30]. note I can only hold 3 smallest values and it store them as I place them.
I also understand that there are a lot of better ways for doing this but again this is just for learning purposes.
Question: I need help creating add method. I wrote some code but I am getting stuck with add method. Please help.
My Thinking: we might have to use a Iterator in add method?
public class MyJavaApp {
public static void main(String[] args){
MyClass<Integer> m = new MyClass<Integer>(3);
m.add(10);
m.add(20);
m.add(30);
m.add(40);
}
}
public class MyClass<V extends Comparable<V>> {
private V v[];
public MyClass(int s){
this.v = (V[])new Object[s];
}
public void add(V a){
}
}
Here is a rough sketch of the add method you have to implement.
You have to use the appropriate implementation of the compareTo method when comparing elements.
public void add(V a){
V temp = null;
if(a.compareTo( v[0]) == -1 ){
/*
keeping the v[0] in a temp variable since, v[0] could be the second
smallest value or the third smallest value.
Therefore call add method again to assign it to the correct
position.
*/
temp = v[0];
v[0] = a;
add(temp);
}else if(a.compareTo(v[0]) == 1 && a.compareTo(v[1]) == -1){
temp = v[1];
v[1] = a;
add(temp);
}else if(a.compareTo(v[1]) == 1 && a.compareTo(v[2]) == -1){
temp = v[2];
v[2] = a;
add(temp);
}
}
Therefore the v array will contain the lowerest elements.
Hope this helps.
A naive, inefficient approach would be (as you suggest) to iterate through the values and add / remove based on what you find:
public void add(Integer a)
{
// If fewer than 3 elements in the list, add and we're done.
if (m.size() < 3)
{
m.add(a);
return;
}
// If there's 3 elements, find the maximum.
int max = Integer.MIN_VALUE;
int index = -1;
for (int i=0; i<3; i++) {
int v = m.get(i);
if (v > max) {
max = v;
index = i;
}
}
// If a is less than the max, we need to add it and remove the existing max.
if (a < max) {
m.remove(index);
m.add(a);
}
}
Note: this has been written for Integer, not a generic type V. You'll need to generalise. It also doesn't keep the list sorted - another of your requirements.
Here's an implementation of that algorithm. It consists of looking for the right place to insert. Then it can be optimized for your requirements:
Don't bother looking past the size you want
Don't add more items than necessary
Here's the code. I added the toString() method for convenience. Only the add() method is interesting. Also this implementation is a bit more flexible as it respects the size you give to the constructor and doesn't assume 3.
I used a List rather than an array because it makes dealing with generics a lot easier. You'll find that using an array of generics makes using your class a bit more ugly (i.e. you have to deal with type erasure by providing a Class<V>).
import java.util.*;
public class MyClass<V extends Comparable<V>> {
private int s;
private List<V> v;
public MyClass(int s) {
this.s = s;
this.v = new ArrayList<V>(s);
}
public void add(V a) {
int i=0;
int l = v.size();
// Find the right index
while(i<l && v.get(i).compareTo(a) < 0) i++;
if(i<s) {
v.add(i, a);
// Truncate the list to make sure we don't store more values than needed
if(v.size() > s) v.remove(v.size()-1);
}
}
public String toString() {
StringBuilder result = new StringBuilder();
for(V item : v) {
result.append(item).append(',');
}
return result.toString();
}
}

Java is not recognizing an object created as an array [duplicate]

This question already has answers here:
Accessing arrays with methods
(4 answers)
Closed 8 years ago.
I am creating a simple mechanical computer emulator, with virtual counters and punch cards, but I keep getting errors in java.
It creates counters as an array of objects like this:
private static void createcounters(int counternums, int digits,
int[] countervals){
for (int i=0; i<counternums; i++){
try {
if (digits < 1){
System.out.println("Invalid number of digits, reverting to 1 digit");
digits = 1;
}
Counter[] counter = null;
counter[i] = new Counter(digits, countervals[i]);
} catch (Exception ex) {
}
}
}
The object is referenced at a different point in a program to read values and put those in a integer array:
public int[] getcounters(){
int[] countervals = null;
for (int i=0; i<counternums; i++){
countervals[i] = counter[i].ReturnVal;
}
return countervals;
}
Java gives this error on compiliation:
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - cannot find symbol
symbol: variable counter
location: class mechanicalcomputeremulator.Computer
at mechanicalcomputeremulator.Computer.getcounters(Computer.java:49)
at mechanicalcomputeremulator.MechanicalComputerEmulator.main(MechanicalComputerEmulator.java:20)
Java Result: 1
If I reference the counter in the method that the objects are created, the error doesn't appear.
You've got at least four problems:
You're declaring the counter variable as a local variable inside your method. I suspect you meant to declare a field somewhere - or return a reference from the method, and assign it to an instance variable there.
You're initializing the variable to null and then immediately trying to dereference it. How do you expect that to work?
You're declaring a different variable for each iteration of the loop. I strongly suspect you mean to declare one variable and populate the same array in all iterations.
You're catching Exception and just ignoring it. Never do that. (Ideally don't do either part of it.)
So sample better code:
private static void createCounters(int counterNums,
int digits,
int[] counterVals) {
// Moved out of the loop, as it's pointless there.
if (digits < 1) {
// TODO: Throw an exception instead?
System.out.println("Invalid number of digits, reverting to 1 digit");
digits = 1;
}
counter = new Counter[counterNums];
for (int i=0; i < counterNums; i++) {
counter[i] = new Counter(digits, counterVals[i]);
}
}
Or:
private static Counter[] createCounters(int counterNums,
int digits,
int[] countervals) {
if (digits < 1) {
// TODO: Throw an exception instead?
System.out.println("Invalid number of digits, reverting to 1 digit");
digits = 1;
}
Counter[] counter = new int[counterNums];
for (int i=0; i < counterNums; i++) {
counter[i] = new Counter(digits, counterBals[i]);
}
return counter;
}
Note that if counterNums is the same as the length of counterVals, you can remove that parameter and just use counterVals.length.
Counter[] counter in createCounters is a method-scoped variable. It will not be available in a different method. If you want to make it available to all methods in your class then it needs to be a field.
However, you need to be aware you are using static on the createcounters method, so you can't access an instance field unless you remove the static keyword on the method.
You also can't do Counter[] counter = null; and then assign values to it, you need to do Counter[] counter = new Counter[size];. I suspect you also want an expandable array, so should use an ArrayList instead.
public class MyClass {
private Counter[] counter = new Counter[10]; // arbitrary fixed size array
private /*static*/ void createcounters(int counternums, int digits,
int[] countervals){
...
counter[i] = new Counter(digits, countervals[i]);
}
public int[] getcounters(){
int[] countervals = null;
for (int i=0; i<counternums; i++){
countervals[i] = counter[i].ReturnVal;
}
return countervals;
}
}

doubling Array size if full

I have an array of objects. When the array fills up, I want to make a new array twice as large as the old one, and transfer all the elements over. I'm doing something wrong, I think its something to do with I'm not creating the correct reference to the new array. Here's my code, any help figuring this out would be appreciated.
private int DIRECTORY_SIZE = 6;
Entry [] directory = new Entry[DIRECTORY_SIZE];
private int numberOfElements = 0;
public int getNumOfElements(){
return numberOfElements;
}
public void setDirectorySize(int size){
DIRECTORY_SIZE = size;
}
public int getDirectorySize(){
return DIRECTORY_SIZE;
}
public void addEntry(String surname, String initial, String num) {
// TODO add an entry to an array, also increments numberOfElements variable tracking whats in array
if(getNumOfElements() == getDirectorySize()){ // if array is full
doubleArraySize(); // put temp values into new bigger directory array
}
int i = findFreeLocation();
directory[i] = new Entry(surname, initial, num);
numberOfElements++;
}
private void doubleArraySize(){
Entry[] temp = new Entry[DIRECTORY_SIZE]; //make new temp array same size as old one
for(int i = 0; i < DIRECTORY_SIZE ; i++){
temp[i] = directory[i]; // cycle through array putting all values into temp
// works up to here
}
setDirectorySize(DIRECTORY_SIZE*2); // double size of array
Entry[] directory = new Entry[DIRECTORY_SIZE]; // create new, double size directory array
for(int i = 0; i < temp.length ; i++){
directory[i] = temp[i];
}
}
private int findFreeLocation() {
int i;
for (i = 0; i < DIRECTORY_SIZE; i++)
{
if(directory[i] == null)
{
break;
}
}
return i;
}
In doubleArraySize() function , this is the issue :
Entry[] directory = new Entry[DIRECTORY_SIZE];
// you are not assigning it to the class attribute directory
// instead you are creating a local array directory
Make the following change :
this.directory = new Entry[DIRECTORY_SIZE];
// this will assign the newly created array to the class attribute
Note : I personally prefer to use this pointer to refer to class attributes so that it makes my code more readable, and its clear to everyone that the variable in question is a class attribute rather than local variable.
**SIZE has already double by this point. No need to multiple by 2
I remember doing something exactly like this when I was making a Vector ADT. However, I used instance variables instead of methods in my code for element number and the capacity. I definitely didn't initialize a Vector inside a method for a Vector.
setDirectorySize(DIRECTORY_SIZE*2); // double size of array
Entry[] directory = new Entry[DIRECTORY_SIZE]; // create new, double size directory array
Isn't DIRECTORY_SIZE an instance variable? Because if it is, I don't think you can initialize an object using an instance variable from the object you are overwriting.
Putting my code into your context, it would look something like this:
private void doubleDirectorySize()
{
Entry[] new_array = new Entry[new_directory_size*2];
for (int i = 0; i < directory_size; i++)
{
new_array[i]= directory[i];
}
directory= new_array;
}
This only works if directory was initialized to null, though, moving the pointer directory to the new array.

Categories