Recreating Arraylist class - java

I'm working on recreating the ArrayList class. I have a problem with the add method. I want my add method to return the new table and to affect it to my element. But when I want to get into the element of my table element it's always null.
And another question..I wanna Create the constructor that takes objects as the elements of the Arraylist like ArrayListBis(1,2,3)..what's gonna be the parameter of the contractor is it ArrayListBis(Object... args) ?
public class ArrayListBis {
final static int DEFAULTSIZE=50;
private int indexCourant,dernierElement,size;
private Object [] elements;
public ArrayListBis(int size){
elements=creatList(size);
indexCourant=0;
dernierElement=size-1;
this.size=size;
}
public void add(Object o){
add(o,size());
}
public void add(Object o, int index){
Object[] temp;
if(index <0 || index > size())
throw new IndexOutOfBoundsException();
else{
temp=creatList(size()+1);
for(int i=0;i!=size()+1;i++){
if(i<index)
temp[i]=elements[i];
else if(i==index)
temp[i]=elements[index];
else
temp[i]=elements[i+1];
}
this.size++;
elements=temp;
}
}

There a couple issues with your add method. First, you do not need to recreate your list every time a new element is added. The reason is that your list will not start out full, hence this line
add(o,size());
should only be done on the condition that this.size == elements.length. However, I believe you should use size or some variable to reflect the actual count of how many elements were inserted so far into your arraylist. So in your constructor, I would set this.size = 0 instead since it starts out with zero elements. Now in your original add method, only create a new array if you're adding to an array that's full. And like others have said, you weren't adding the new element to begin with. So with those changes it should now look like this,
public void add(Object o, int index){
Object[] temp;
if(index >= 0 && index < elements.length)
temp[index] = o;
size++;
else{
temp=creatList(elements.length * 2);
for(int i=0;i < elements.length;i++){
if(i<index)
temp[i]=elements[i];
else if(i==index)
temp[i]=o;
else
temp[i]=elements[i+1];
}
temp[index] = 0;
size++;
this.elements = temp;
}
}
Only other thing I changed was how much the new list's size should be. I changed it to be double the original array's size because you don't want to make a new array of a size that's only one more bigger than the original because making new arrays and copying all the elements from the old one to the new one is a costly operation that shouldn't be done too often.

Related

Comparing the values of two arrays using recursion?

I am trying to check if two arrays have the same length, and the same values in the same exact position.
My current code looks like this:
public class MyArray {
private int size;
private int[] array;
private boolean isSorted; //to check if array is sorted
private static int arrCount; //used to identify which MyArray object
public MyArray(){
size = 10;
array = new int[10];
arrCount+=1;
}
public MyArray(int Size){
size = Size;
array = new int[Size];
arrCount+=1;
}
public MyArray(MyArray arrOther){
this.size = arrOther.getSize();
this.array = arrOther.getArray();
arrCount+=1;
}
public int getSize(){
return size;
}
public int[] getArray(){
return array;
}
#Override
public boolean equals(Object other){
if (other instanceof MyArray){
MyArray second = (MyArray) other;
if (second.getSize() == this.getSize())
return equalsHelper(this.getArray(), second.getArray(), 0, (size-1));
}
//else
return false;
}
private boolean equalsHelper(int[] first, int[] second, int iStart, int iEnd) {
if (iStart == iEnd) {
return true;
}
if (first[iStart] == second[iStart]) {
if (equalsHelper(first, second, (iStart + 1), iEnd)) {
return true;
}
}
return false;
}
}//end class
for some reason it always returns true even if the arrays are in different order.
the equals method is called in the main program here:
--main method--
if (MA2.equals(MA1)) //the arrays are identical here
{
System.out.println("The first and second arrays are equal.");
}
else {System.out.println("The first and second arrays are NOT equal.");}
MA2.sort(); //the order of the elements changes
System.out.println("The second array has been sorted in ascending order.");
if (MA2.equals(MA1))
{
System.out.println("The first and second arrays are equal.");
}
else {System.out.println("The first and second arrays are NOT equal.");}
First check (preferably) outside of your helper should be to see if both the arrays have equal lengths. Makes no sense to continue otherwise.
equalsHelper should return true if end of array is reached.
I see no reason to have 2 separate pointers for index since the arrays are required to be of the same size and the same index is being checked.
Invocation:
....
....
if(first.length != second.length)
return false;
return equalsHelper(first, second, 0);
The helper method...
private boolean equalsHelper(int[] first, int[] second, int indx) {
if(indx == first.length)
return true;
if(first[indx] != second[indx)
return false;
return equalsHelper(first, second, indx+1);
}
Firstly, iStart and iEnd are redundant. use .length
String[] array = new String[10];
int size = array.length;
If you're trying to compare contents of arrays that may be identical, you need to pass through it manually.
for(int i = 0: (i > first.length || i > second.length; i++){
if(first[i] != second[i]){
return false;
}
}
return true
Your next problem is
if (iStart == iEnd){
return first[iEnd] == second[iEnd]; //return true or false
Your logic here is wrong. You can't directly compare arrays like this. It's comparing the memory address. This will always be false unless you pass through the exact same array when the method is called - which i don't think is what you're trying to do
Array lengths are set manually, so it's a conscious effort to get a difference.
Let me suggest using an ArrayList if you're expecting differing lengths. They're also more flexible.
ArrayList <Integer> a = new ArrayList <int>();
ArrayList <Integer> b = new ArrayList <int>();
Then you'll need to check their lengths. ArrayList uses the .length() method instead of an Array[].length property
if(a.length() == b.length()){
then if you want to see if each value in each index is identical, you'll need to pass through the array manually as shown above.

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();
}
}

Insert elements into array in sorted order

I have written this code for insert and remove elements into and from array. But I want to insert elements into array in sorted order. How can I improve my "add" method? And I also don't know the implementation of the "remove" method. How can I implement remove method
public void add(int index, String str) {
// First make sure the index is valid.
if (index > elements || index < 0) {
throw new IndexOutOfBoundsException();
}
// If the list is full, resize it.
if (elements == list.length) {
resize();
}
// Shift the elements starting at index
// to the right one position.
for (int index2 = elements; index2 > index; index2--) {
list[index2] = list[index2 - 1];
}
// Add the new element at index.
list[index] = str;
// Adjust the number of elements.
elements++;
}
public boolean remove(String str) {
return false;
}
After filling the array, call:
Arrays.sort(array)
You are resizing the array, why dont you simply use a List?
List<Type> list = new ArrayList<Type>();
Collections.sort(list);
I suppose you should sort array not on adding element but when you return it. For decreasing array accesses you may use flag that will indicate that array must be resorted, i.e.
private boolean hasNew = false;
public void add (int index, String str) {
// Your code
hasNew = true;
}
public int[] getArray() {
if (hasNew) Arrays.sort(list);
return list;
}
This is the general idea, but feel free to adopt it.

Java Stack with elements limit

I know this question has asked many times but after seaching for an hour i still have problem.
I want to use a lifo stack which has a max number of elements it can store.After it reach the max number is deletes the element at first place and replace it with the new so in first pop i can get this element and in second i have to get the element at size-1.
What i tried:
1) Using a modified Stack ,as described here .The problem is that it always returning the first 5 elements(if the size is 5) i added.
class StackSizable<E> extends Stack<E>{
int maxSize;
StackSizable(int size)
{
super();
this.maxSize=size;
}
#Override
public E push(E elt) {
super.push(elt);
while (this.size() > this.maxSize) {
this.removeElementAt(this.size() - 1);
}
return null;
}
}
2)Using an ArrayDeque ,i dont see any diference from a simple Stack , its not setting any limit(am i using it wrong?)
ArrayDeque<State> lifo = new ArrayDeque<State>(5);
lifo.pop();
lifo.push(state);
I want to use this in a puzzle game for undo-redo functionality
Solved: I ended using a fixed size stack as tom said ,mainly for the performance
public class FixedStack<T> {
private T[] stack;
private int size;
private int top;
private int popBalance = 0;//its used to see if all the elements have been popped
public FixedStack(T[] stack) {
this.stack = stack;
this.top = 0;
this.size = stack.length;
}
public void push(T obj) {
if (top == stack.length)top = 0;
stack[top] = obj;
top++;
if (popBalance < size - 1)popBalance++;
}
public T pop() {
if (top - 1 < 0)top = size;
top--;
T ob = stack[top];
popBalance--;
return ob;
}
public void clear() {
top = 0;
}
public int size() {
return size;
}
public boolean poppedAll() {
if (popBalance == -1)return true;
return false;
}
}
I think the most efficient way to this is with a fixed array, with size equal to your max # of elements, and an index that points to the element that is currently the 'top' of the queue.
When you add a new element you add it at index+1 (wrapping back to element 0 if necessary) and possibly overwriting an element that no longer fits. When you pop an element you do the reverse.
This way your data structure never has to be re-ordered, and you can use an array which is more light-weight then a collection.
When the maximum size has been reached, your line
this.removeElementAt(this.size() - 1);
then immediately removes the last pushed element (which you just pushed), which is the top of the stack. You need to remove the first element instead (bottom of the stack):
this.removeElementAt(0);

Could someone give my code for a deque a quick once over please?

Been working on this for a while now and I think I've finally cracked it, it's working for all my tests, but I have a feeling there will be some niggling issues. This is a heavily simplified version of a double sided queue (deque) where every time a value is added, a temporary array is made to store all values, and then the new value appended on. It is easiest to explain this way, I believe. If someone could please just double-check I am correct and there is nothing glaringly wrong here, I would be extremely thankful. Thank you all very much ! :)
public class ArrayBasedDeque<EltType> implements Deque<EltType> {
private final int CAPACITY = 10;
private int capacity;
private int end;
private EltType deque[];
public ArrayBasedDeque() {
this.capacity = CAPACITY;
deque = (EltType[]) (new Object[capacity]);
}
public EltType first() {
return deque[0];
}
public EltType last() {
return deque[end-1];
}
public boolean isEmpty() {
return end == 0;
}
public int size() {
return deque.length;
}
public boolean isFull() {
return end == capacity;
}
public void insertFirst(EltType inserted) {
if (!isEmpty()) {
EltType[] tempArray;
capacity+=1;
tempArray = (EltType[]) new Object[capacity];
for(int i=0;i<end;i++){
tempArray[i+1] = deque[i];
}
deque=tempArray;
}
deque[0] = inserted;
end++;
}
public void insertLast(EltType last) {
if (isFull()){
EltType[] tempArray;
capacity+=1;
tempArray = (EltType[]) new Object[capacity];
for (int i=0;i<end;i++) {
tempArray[i] = deque[i];
}
// System.out.print(deque[end]);
}
deque[end] = last;
end++;
}
public EltType removeFirst() {
EltType[] tempArray;
EltType returned = deque[0];
tempArray = (EltType[]) new Object[capacity];
for (int i=1;i<capacity;i++) {
tempArray[i-1] = deque[i];
}
deque = tempArray;
end--;
return returned;
}
public EltType removeLast() {
EltType[] tempArray;
EltType returned = deque[end-1];
tempArray = (EltType[]) new Object[capacity];
for (int i=0;i<capacity;i++) {
tempArray[i] = deque[i];
}
deque = tempArray;
end--;
return returned;
}
}
A few comments:
I would use T or E as the name of the type parameter, rather than EltType
I'd rename the constant CAPACITY to DEFAULT_CAPACITY, and make it static.
first() will return a value even if the deque is logically empty
last(), removeLast() and removeFirst() should throw an appropriate exception if end is 0
There's no point in having a capacity separate from the size unless you're using that to avoid creating a new array each time. If you're always going to expand/shrink the array on any change, just use the array on its own - you can tell the size just from the array's length
In removeFirst and removeLast your loop bound is capacity instead of end
Use System.arraycopy as a simpler way to copy arrays
You haven't got an assignment to deque in insertLast - hence the exception you're seeing in the comments.
I'm not sure I see the benefit of having this over just using ArrayList<T> though... the main point of having a separate Deque implementation would be to make adding to both head and tail cheap... here we have neither!
... or of course just use ArrayDeque or LinkedList :)
I would suggest
don't create a new Object[] every time you add or remove an entry.
Use System.arrayCopy() instead of manual copy.
You don't need to copy up to the capacity, only up to the end.
you could use a ring buffer to avoid needing to move elements around (no need for copies)
Drop Based from the name ArrayDeque is more consistent with ArrayList, ArrayBlockingQueue, etc.

Categories