I am working on creating a bag of cards for a blackjack game in my CS course. This particular project requires that I create a bag to hold my 52 cards. Keep in mind that I am trying to assure that there are 4 types of each card, Queens, Kings, Jacks, and Aces all included. I keep getting an error in my main: Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
at Main.main(Main.java:14)
If anyone can please help me to get this bag running properly, it would be greatly appreciated.
Here is my code:
public class Bag<T>
{
T[] cards;
private final int DEFAULT_CAPACITY = 52;
private int numberOfEntries;
public Bag()
{
this.cards = (T[]) new Object[DEFAULT_CAPACITY];
numberOfEntries = DEFAULT_CAPACITY;
}
public int getCurrentSize()
{
return numberOfEntries;
}
public boolean isFull()
{
return numberOfEntries == DEFAULT_CAPACITY;
}
public boolean isEmpty()
{
return numberOfEntries == 0;
}
public boolean add(T newItem)
{
boolean result = true;
if(isFull())
{
result = false;
}
else
{
cards[numberOfEntries] = newItem;
numberOfEntries++;
}
return result;
}
public boolean remove()
{
boolean result = true;
if(numberOfEntries > 0)
{
numberOfEntries--;
}
else
result = false;
return result;
}
public void clear()
{
numberOfEntries = 0;
}
public int getNumOf(T anItem)
{
int count = 0;
for(int i = 0; i < cards.length; i++)
{
if(anItem.equals(cards[i]))
{
count++;
}
}
return count;
}
public boolean contains(T anItem)
{
boolean found = false;
for (int i = 0; !found && (i < numberOfEntries); i++)
{
if(anItem.equals(cards[i]))
{
found = true;
}
}
return found;
}
public T Grab()
{
int random = (int)(Math.random() * DEFAULT_CAPACITY);
if(!isEmpty())
{
cards[random] = null;
numberOfEntries--;
return cards[random];
}
else
return null;
}
public int getFrequencyOf(T anItem)
{
int counter = 0;
for(int i = 0; i < numberOfEntries; i++)
{
if(anItem.equals(cards[i]))
{
counter++;
}
}
return counter;
}
}
public class Main {
public static void main(String[] args)
{
//Accesses the Bag class
Bag<Integer> bag = new Bag<Integer>();
//Sets up 52 cards (13*4). 4 of each type
for (int i = 1; i <= 13; i++)
{
for (int j = 1; j <= 4; j++) {
bag.cards[i*j] = i;
//if the card is an ace and not equal to 1
if(i == 1)
bag.cards[i*j] = 11;
//handles the king, queen, and jack cards
else if (i==11||i==12||i==13)
bag.cards[i*j] = 10;
}
bag.add(1);
}
}
}
Don't provide access to your T[] cards variable. Make it private and create a set method in your Bag like this:
public void set(int index, T item) {
// assume !full AND 0 <= index < cards.length
this.cards[index] = item;
}
Then, instead of doing:
bag.cards[i*j] = 10;
you then do:
bag.set(i*j, 10);
The fact that you get a class-cast exception is because type erasure: your T[] only lives at compile time. After compilation, it will just have become a Object[]. That is why your direct access cards[0] = 123 throws this exception (Integer 123 cannot be put inside a Object[]).
The set(int index, T value) I suggested works, because after compilation, that will just become set(int index, Object value), and hence: no class-cast exception.
EDIT
You can test the following quick demo:
class Bag<T> {
private T[] cards;
public Bag() {
this.cards = (T[]) new Object[10];
}
public void set(int index, T value) {
this.cards[index] = value;
}
#Override
public String toString() {
return "Bag{cards=" + java.util.Arrays.toString(cards) + "}";
}
public static void main(String[] args) {
Bag<Integer> bag = new Bag<Integer>();
bag.set(0, 10);
bag.set(1, 20);
bag.set(2, 30);
System.out.println(bag);
}
}
on Ideone, which will print:
Bag{cards=[10, 20, 30, null, null, null, null, null, null, null]}
You can also simply remove the generics from your cards variable like this:
class Bag<T> {
private Object[] cards;
public Bag() {
this.cards = new Object[10];
}
public void set(int index, T value) {
this.cards[index] = value;
}
}
For inspiration, you can always have a look at the source of core Java classes that resemble your own. In this case, that would be the java.util.ArrayList: http://www.docjar.com/html/api/java/util/ArrayList.java.html
You cannot cast your Object array to a an Integer array, because its not, it's an Object array. That's what your (T[]) cast is trying to do:
this.cards = (T[]) new Object[DEFAULT_CAPACITY];
You cannot instantiate an array of type T either, unless you pass in the class type explicity - see What's the reason I can't create generic array types in Java?. Possible solutions:
Use Object [] to store you data, i.e. private Object[] cards;
Use a parameterized collections type like List<T>, i.e. private List<T> cards
Related
I have troubles implementing an Iterator for my TupleHashSet class.
The hashArr attribute stores the Hashsets for my Tuple (Pair) objects. The insert method inserts the Tuples according to the calculated HashCode.
The problem is that my iterator doesn't iterate through the entire HashArr if I insert something with the method.
My teacher told me a tip that my approach is wrong since the HashSet value aren't interested in order. However, I'm not sure what he means with that.
TupleSet
public class TupleSet<T, S> implements Iterable<Tuple<T, S>> {
private final Tuple<T, S>[] hashArr;
public static final int SS = 999;
public TupleHashSet() {
hashArr = new Tuple[SS];
}
#Override
public java.util.Iterator<Tuple<T, S>> iterator() {
return new Iterator(hashArr);
}
class Iterator implements java.util.Iterator<Tuple<T, S>> {
private Tuple<T, S>[] array;
private int index = 0;
Iterator(Tuple<T, S>[] t) {
this.array = t;
}
#Override
public boolean hasNext() {
for (int i = index; i < SIZE; ++i) {
if (array[i] != null) {
return true;
}
}
return false;
}
#Override
public Tuple<T, S> next() {
for (int i = index; i < SIZE; ++i) {
if (hashArr[i] != null) {
index = i + 1;
return hashArr[i];
}
}
throw new NoSuchElementException();
}
}
This answer addresses your question about the iterator not returning all items.
The array index is never incremented, so it will always return the item at index 1, which is index + 1. index must be incremented in the call to next before returning so that the next call starts at the subsequent element in the backing array.
Also, the backing array is not dense (meaning there could be empty slots at arbitrary positions, and that's OK), so the next function has to find the next valid entry, not just give up if the next entry is empty (i.e. null).
Try this instead:
#Override
public Iterator<Tuple<T, S>> iterator() {
Iterator<Tuple<T, S>> it = new Iterator<Tuple<T, S>>() {
private int index = 0;
#Override
public boolean hasNext() {
for (int i = index; i < SIZE; ++i) {
if (hashArr[i] != null) {
return true;
}
}
return false;
}
#Override
public Tuple<T, S> next() {
for (int i = index; i < SIZE; ++i)
if (hashArr[i] != null) {
index = i + 1;
return hashArr[i];
}
}
throw new NoSuchElementException();
}
};
return it;
}
Here's a possible solution.
public boolean hasNext() {
for(; index < SIZE && hashArr[index] == null; index++);
return index < SIZE;
}
I am trying to check whether my levelorder of my Binary Search Tree is equal to the other one. To do this, I tried to make a compareTo method. I only give equal values to the method, but it keeps on saying the condition is false. When I place breakpoints, I see that the values are still equal. I am probably not understanding it correctly. Does anyone know how to solve this?
Here is what I did, as you can see below, the compareTo returns a 1 instead of a 0:
import edu.princeton.cs.algs4.BST;
import java.util.*;
public class MyBST implements Comparable<MyBST>{
private Object e;
public MyBST(Object e){
this.e = e;
}
private Object getE(){
return e;
}
public static void main(String[] args) {
int size = 4;
Random r = new Random();
Set<Integer> tes = new LinkedHashSet<>(size);
Stack<Integer> stack = new Stack<>();
while (tes.size() < size) {
tes.add(r.nextInt(10));
}
System.out.println("possible combinations");
Set<Stack<Integer>> combos = combos(tes, stack, tes.size());
Object[] arr = combos.toArray();
List<String> d = new ArrayList<>();
for (Object s : arr) {
String b = s.toString();
b = b.replaceAll("\\[", "").replaceAll("\\]", "");
d.add(b);
}
int index = 0;
do {
BST<String, Integer> bst1 = new BST<String, Integer>();
BST<String, Integer> bst2 = new BST<String, Integer>();
String key1 = d.get(index);
String key2 = d.get(index);
key1 = key1.replaceAll(" ", "");
String[] m = key1.split(",");
key2 = key2.replaceAll(" ", "");
String[] n = key2.split(",");
System.out.println("1e order");
for (int j = 0; j < m.length; j++) {
System.out.println(m[j]);
bst1.put(m[j], 0);
}
System.out.println("2e order");
for (int j = 0; j < n.length; j++) {
System.out.println(n[j]);
bst2.put(n[j], 0);
}
System.out.println("levelorder 1e BST");
MyBST e = new MyBST(bst1.levelOrder());
MyBST y = new MyBST(bst2.levelOrder());
System.out.println(bst1.levelOrder());
System.out.println("levelorder 2e BST");
System.out.println(bst2.levelOrder());
System.out.println(e.compareTo(y) + "\n");
index++;
} while (index < arr.length - 1);
}
public static Set<Stack<Integer>> combos(Set<Integer> items, Stack<Integer> stack, int size) {
Set<Stack<Integer>> set = new HashSet<>();
if (stack.size() == size) {
set.add((Stack) stack.clone());
}
Integer[] itemz = items.toArray(new Integer[0]);
for (Integer i : itemz) {
stack.push(i);
items.remove(i);
set.addAll(combos(items, stack, size));
items.add(stack.pop());
}
return set;
}
#Override
public int compareTo(MyBST o) {
if (this.e == o.e) {
return 0;
}
else
return 1;
}
}
Here you can find the BST.java class: BST.java
And the output is something like:
The breakpoint at the compareTo method says:
When you're using the == operator you're actually checking to see if the references point to the same object in memory. From your debugging screenshot you can see that they are not. this.e points to object Queue#817 while o.e points to Queue#819.
If all you want to do is test for equality, then just override equals and hashCode. You can do it like this (rest of class omitted):
public class MyBST {
private Object e;
public MyBST(Object e) {
this.e = e;
}
public Object getE(){
return e;
}
#Override
public int hashCode() {
return Objects.hashCode(e);
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof MyBST))
return false;
MyBST me = (MyBST) obj;
if (e == null) {
if (me.e != null)
return false;
} else if (!e.equals(me.e))
return false;
return true;
}
}
Implementing Comparable is more involved since you need to check for less, equal, or greater than other instances of MyBST. Unfortunately, the only field in MyBST is an Object which does not tell you anything about its actual fields. So without specific fields with which to test you need to ensure that the Object you pass also implements Comparable. Then you can declare your class like this. Rest of class omitted.
It simply says that
MyBST is comparable.
And the object that is passed in the constructor is comparable.
class MyBST<T extends Comparable<? super T>> implements Comparable<MyBST<T>>{
private T e;
public MyBST(T e){
this.e = e;
}
public T getE(){
return e;
}
#Override
public int compareTo(MyBST<T> o) {
return e.compareTo(o.e);
}
}
The other alternative is to simply pass the actual object type and store it as such, not as Object. Then just implement Comparable in MyBST and use the appropriate fields of the passed object. Lets say the object was an Apple object, you could do this.
class Apple {
String type;
int weight;
}
class MyBST implements Comparable<MyBST> {
private Apple apple;
public MyBST(Apple apple) {
this.apple = apple;
}
#Override
public int compareTo(MyBST e) {
// this could be different depending on how you wanted
// to compare one apple to another. This comparison favors
// type over weight.
// check type - String class implements comparable
int ret = apple.type.compareTo(e.apple.type);
if (ret != 0) {
return ret;
}
// same type so check weight
if (apple.weight < e.apple.weight) {
return -1;
}
if (apple.weight > e.apple.weight) {
return 1;
}
return 0; // equals apples based on criteria
}
}
Finally, you have this.
private Object getE(){
return e;
}
A private getter is not usually very useful. Make it public.
I have a method to add a collection of generic elements to my array but do not know how to implement this. I have symbolised the line of code that I have been having trouble with as COLLECTION. I do not know what to write in place of this. My array is a circular ring array.
import java.util.Collection;
import java.util.Iterator;
public class CircularArrayRing<E> implements Ring<E> {
public E[] elements; //array of E
private int capacity;
private int writePos = 0;
private int available = 0;
public CircularArrayRing(int size) { //circular array constructor
capacity = size;
}
public boolean add(E e) {
if(available < capacity){
if(writePos >= capacity){
writePos = 0;
}
elements[writePos] = e; //add element e
writePos++;
available--;
return true;
}
return false;
}
public boolean addAll(Collection<? extends E> c) {
if(available < capacity){
if(writePos >= capacity){
writePos = 0;
}
elements[writePos] = COLLECTION; //how do add a collection of elements?
writePos++;
available++;
return true;
}
return false;
}
}
What about iterating and triggering add() one by one?
public boolean addAll(Collection<? extends E> c){
for(E e : c){
add(e);
}
}
The functional way.
c.forEach(this::add);
You can find out some ideas here:
https://github.com/bekkopen/Continuous-Delivery-example/blob/master/webapp/src/main/java/no/bekk/bekkopen/cde/jetty/config/CollectionBuilder.java#L10
public static <T> Set<T> newSet(final T... elements) {
return new HashSet<T>(Arrays.asList(elements));
}
public static <T> List<T> newList(final T... elements) {
return new ArrayList<T>(Arrays.asList(elements));
}
Here is some examples:
public void testCollectionAdd() {
if (!isAddSupported()) return;
Object[] elements = getFullElements();
for (int i = 0; i < elements.length; i++) {
resetEmpty();
boolean r = collection.add(elements[i]);
confirmed.add(elements[i]);
verify();
assertTrue("Empty collection changed after add", r);
assertTrue("Collection size is 1 after first add",
collection.size() == 1);
}
resetEmpty();
int size = 0;
for (int i = 0; i < elements.length; i++) {
boolean r = collection.add(elements[i]);
confirmed.add(elements[i]);
verify();
if (r) size++;
assertEquals("Collection size should grow after add",
size, collection.size());
assertTrue("Collection should contain added element",
collection.contains(elements[i]));
}
}
Full code here:
http://code.openhub.net/file?fid=WKY7Buaz9RI_B0BqM_HKnkm6lqY&cid=9RkvURzZ1wM&s=How%20to%20Add%20a%20collection%20of%20elements%20to%20my%20array%3F&pp=0&fl=Java&ff=1&projSelected=false&filterChecked,=true&mp,=1&filterChecked=true&mp=1&ml=1&me=1&md=1#L79
So i am trying to make an array based generic heap that i can use with my tester class. Much of what i have is based of my understandings of trees and some research online as well as from my textbook; both which have very limited info on what i am looking for. However, i did manage to get all the methods in need and when i run it, i get this error:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
at q1.Heaps.<init>(Heaps.java:23)
at q1.createGui.<init>(Gui.java:46)
at q1.Gui.main(Gui.java:18)
Im guessing it has to do with how i declare and initialize my Comparable array, which i am having trouble figuring out how to.
package q1;
import java.util.Arrays;
public class Heaps<E extends Comparable<E>> {
Comparable[] data;
int size;
/**
* Constructor with s as size
*/
#SuppressWarnings("unchecked")
public Heaps(int s) {
size = 0;
data = (E[]) new Object[s];
}
/**
* Adds a value to the heap
*/
public void add(E value) {
if (full()) // expand array
ensureCapacity(2*size);
size++;
data[size] = value;
if (size > 1)
heapifyUp();
}
/**
* Checks if the array is full
*/
private boolean full()
{
return (size == data.length-1);
}
private void heapifyUp()
{
Comparable<E> temp;
int next = size;
while (next != 1 && data[next].compareTo(data[next/2]) > 0)
{
temp = data[next];
data[next] = data[next/2];
data[next/2] = temp;
next = next/2;
}
}
private void heapifyDown()
{
Comparable<E> temp;
int next = 0;
while (next*2 <= size) // node has a child
{
int child = 2*next; // left child
if (child < size &&
data[child].compareTo(data[child+1]) > 0)//left smaller than right
child++; // right child instead
if (data[next].compareTo(data[child]) > 0)
{
temp = data[next];
data[next] = data[child];
data[child] = temp;
next = child;
}
else;
next = size; // stop loop
}//end while
}
/**
* Removes all occurrence of element
*/
public boolean removeAll(E element) {
if (contains(element) && !(isEmpty())){
for (int i = 0; i < size; i++){
if(element.equals(data[i])){
data[i] = data[size-1];
}
heapifyDown();
}
return true;
}
return false;
}
/**
* Removes 1st occurrence of element
*/
public boolean remove(E element) {
if (contains(element) && !(isEmpty())){
for (int i = 0; i < size; i++){
if(element.equals(data[i])){
data[i] = data[size-1];
heapifyDown();
return true;
}
}
}
return false;
}
public boolean isEmpty() {
return size == 0;
}
public Comparable<E>[] ensureCapacity(int s) {
return Arrays.copyOf(data, 2*s);
}
/**
* Converts the heap into its String representation.
* #return the String representation
*/
public Comparable<E>[] iteratorPreOrder()
{
Comparable<E>[] temp = (E[]) new Object[size];
temp[0] = data[0];
int i = 1;
int count = 1;
while(data[2*i] != null){
temp[count] = data[2*i];
++i;
++count;
}
i = 1;
while(data[(2*i) +1] != null){
temp[count] = data[(2*i) +1];
++i;
++count;
}
return temp;
}
public int countOccurance(E element){
int count = 0;
for (int i =0; i < size; i++){
if(element.equals(data[i])){
count++;
}
}
return count;
}
public boolean contains (E element)
{
for (int i=0; i<size; i++){
if (element.equals(data[i])){
return true;
}
}
return false;
}
}
If you could please show me how i would solve this problem, i would greatly appreciate it. Thanks
EDIT: SO i edited the my class and now it works when i do data = (E[]) new Comparable[s]. So why does java not allow generic Array types, what makes it different from Arraylist, Stacks, Queues, and/or LinkedList which can be generic?
You are creating an Object[] and then trying to cast it to a Comprable[]. The compiler was telling you what you did wrong with the unchecked cast error.
You want data to be E[] data and the line to be:
data = new E[s];
Note: this could run into issues with how Java handles generics.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
Long story short, I am in a university Comp Sci class, and the Professor wants us to build a Vector but from scratch. Are their any good tutorials on the web for something like this? I did a Google search but nothing really came up.
EDIT
According to the document the teacher gave out the vector needs to be able to do the following:
append(Object element) – appending the element at the end of the vector
clear() – make the vector collection empty
contains(Object element) – check whether the vector contains the element
elementAt(int index) – access the element at the given index
indexOf(Object element) – find the index of the element
insertAt(int index, Object element) – insert the element at the given index
isEmpty() – check whether the vector is empty
removeAt(int index) – remove the element at the given index
remove(Object element) – remove the element from the vector
replace(int index, Object element) – replace the element at the given index with the given element
size() – get the number of elements in the current vector
ensureCapacity(int minCapacity) – make sure the vector gets at least the given capacity
clone() – returns a cloned copy of this vector
removeRange(int fromIndex, int toIndex) – removes from this vector all of the elements whose index is between fromIndex, inclusive and toIndex, exclusive
toString() – returns a string representation of this vector, containing the String representation of each element
reverse() – reverse the elements in this vector
merge(MyVector vector2) – add all the elements in vector2 to the end of this vector
Additionally the class needs to implment Cloneable and be self expanding.
This is what I have come up with so far:
package collection;
public class MyVector implements Cloneable {
protected Object[] items;
protected int arraySize;
protected int maxCap;
public MyVector (int initialCapacity) {
super();
if (initialCapacity < 0) {
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
this.items = new Object[initialCapacity];
this.arraySize = 0;
this.maxCap = initialCapacity;
}
public MyVector() {
this(10);
}
public void append(Object element) {
int newArraySize = this.arraySize + 1;
if(this.maxCap == newArraySize) {
this.items = this.increaseCap(newArraySize);
this.items[this.arraySize] = element;
this.arraySize += 1;
//System.out.println(this.items[this.arraySize);
} else {
this.items[this.arraySize] = element;
this.arraySize +=1;
}
}
#Override
public String toString() {
String output = "[";
//output = this.items[0].toString();
for(int i = 0; i < this.arraySize; i++) {
output += this.items[i] + ", ";
}
output += "]";
return output;
}
public void clear() {
for(int i = 0; i < this.arraySize; i++) {
this.items[i] = null;
this.arraySize = 0;
}
}
public boolean contains(Object element) {
boolean doesContain = false;
for(int i = 0; i < this.arraySize; i++) {
if(element == this.items[i]) {
doesContain = true;
i = this.arraySize;
}
}
return doesContain;
}
public Object elementAt(int index) {
if(this.arraySize >= index) {
return this.items[index];
} else {
Object temp = null;
System.out.println("No index of " + index);
return temp;
}
}
public Object indexOf(Object element) {
Object index = "No value found";
for(int i = 0; i < this.arraySize; i++) {
if(element == this.items[i]) {
index = i;
break;
}
}
return index;
}
public boolean isEmpty() {
if(this.arraySize == 0) {
return true;
}
return false;
}
public void replace(int index, Object element) {
if(this.arraySize > index) {
this.items[index] = element;
} else {
System.out.println("No element at " + index);
}
}
public int size() {
return this.arraySize;
}
public void reverse() {
Object[] temp = new Object[this.items.length];
int j = this.arraySize;
for(int i = 0; i < this.arraySize; i++) {
temp[j] = this.items[i];
j--;
}
this.items = temp;
}
public void ensureCapacity(int minCapacity) {
if(minCapacity > this.items.length) {
this.items = this.increaseCap(minCapacity);
}
}
public Object[] increaseCap(int minCap) {
Object[] arr1 = new Object[minCap * 2];
for(int i = 0; i < minCap; i++) {
arr1[i] = this.items[i];
}
this.maxCap = this.maxCap * 2;
return arr1;
}
#Override
public Object clone() {
return this.items;
}
public boolean checkIndex(int index) {
boolean check = false;
if(index < this.arraySize) {
check = true;
}
return check;
}
public void removeAt(int index) {
if(true == this.checkIndex(index)) {
Object[] temp = new Object[this.arraySize - 1];
for(int j = 0; j < index; j++) {
temp[j] = this.items[j];
}
for(int j = index + 1; j < this.arraySize; j++) {
temp[j-1] = this.items[j];
}
this.items = temp;
this.arraySize = this.arraySize - 1;
}
}
public void insertAt(int index, Object element) {
if (this.checkIndex(index) == true) {
Object[] temp = new Object[this.arraySize];
for(int i = index; i < this.arraySize; i++) {
temp[i+1] = this.items[i];
}
this.items[index] = element;
for (int i = index + 1; i < this.arraySize; i++) {
this.items[i] = temp[i - 1];
}
this.arraySize = this.arraySize - 1;
}
}
public void remove(Object element) {
for(int i = 0; i < this.items.length; i++) {
if(this.items[i] == element) {
this.removeAt(i);
}
}
}
public void removeRange(int fromIndex, int toIndex) {
for(int i = fromIndex; i < toIndex; i++) {
this.removeAt(i);
}
}
public void merge(MyVector vector2) {
this.ensureCapacity(vector2.size() + this.arraySize);
for(int i = 0; i < vector2.size(); i++) {
this.append(vector2);
}
}
}
Assuming your assignment is replicating java.util.Vector, I would look at what a Vector is in order to replicate it:
Vector implements a dynamic array. It is similar to ArrayList, but
with two differences:
Vector is synchronized.
Vector contains many legacy methods that are not part of the collections framework.
You could attempt to use an ArrayList in a synchronous manner in order to replicate a Vector, but I'm sure there are much better solutions.