ObjectList Java task - java

I have been given the following main method and must write the code for the ObjectList class. I am supposed to infer the necessary functions of the ObjectList class and write the class myself, however I am unsure exactly what I need to do to fulfill this function. Any help understanding this is greatly appreciated. This is the code I was given:
ObjectList ol = new ObjectList(3);
String s = "Im Happy";
Dog d = new Dog();
DVD v = new DVD();
Integer i = 1234;
System.out.println(ol.add(s));
System.out.println(ol.add(d));
System.out.println(ol.add(v));
System.out.println(ol.add(i));
ol.remove(0);
System.out.println(ol.add(i));
System.out.println("Is the list full? "+ isFull());
System.out.println("Is the list empty? "+ isEmpty());
System.out.println("Total number of objects in the list: " + getTotal());
Object g = ol.getObject(1);
g.bark();

It's quite simple just need to create a list of Object types using ArrayList or LinkedList in the ObjectList class and implement the function as follows
public class ObjectList{
private ArrayList<Object> objects;
public ObjectList(int size)
{
objects = new ArrayList<Object>(size);
}
public String add (Object object)
{
objects.add(object);
//anything you would like to return I'm just returning a string
return "Object Added";
}
public void remove (int index)
{
objects.remove(index);
}
public boolean isEmpty()
{
return objects.isEmpty();
}
public int getTotal()
{
return objects.size();
}
public Object getObject(int index)
{
return objects.get(index);
}
}
The isFull()is not needed since ArrayListsize can change dynamically. You can use a simple array instead of ArrayList and then implement the isFull() function.
Also when getting an object using the get getObject() function, you need to cast it to the correct type before using there function. In your code g.bark() won't work because Object doesn't have a bark function
Object g = ol.getObject(1);
//This can give a runtime error if g is not a Dog
//Use try catch when casting
Dog d = (Dog)g;
d.bark();
EDIT
This is how you would implement isFull() and other functions if using arrays instead of ArrayList but for the sake of simplicity use the ArrayList version
public class ObjectList{
private Object[] objects;
private int size = 0;
private int currentIndex = 0;
public ObjectList(int size)
{
this.size = size;
objects = new Object[size];
}
private boolean isFull() {
if(currentIndex == size)
return true;
else
return false;
}
public String add (java.lang.Object object)
{
if ( ! isFull() ) {
objects[currentIndex] = object;
currentIndex++;
return "Object added";
}
return "List full : object not added";
}
public void remove (int index)
{
if( !isEmpty() ) {
//shifting all the object to the left of deleted object 1 index to the left to fill the empty space
for (int i = index; i < size - 1; i++) {
objects[i] = objects[i + 1];
}
currentIndex--;
}
}
public boolean isEmpty()
{
if(currentIndex == 0)
return true;
else
return false;
}
public int getTotal()
{
return currentIndex;
}
public java.lang.Object getObject(int index)
{
if(index < currentIndex)
return objects[index];
else
return null;
}
}

What it seems you want to achieve is "expand" the functionality of an ArrayList and create a custom list of objects. What you could do is to create a class extending the ArrayList and define/override any other methods you want.
public class ObjectList extends ArrayList<Object> {
//constructor with initial capacity
private int length;
public ObjectList(int size){
super(size);
this.length= size;
}
public Object getObject(int index){
return this.get(index);
}
}
Now you have the add and remove functions inherited from the ArrayList class and the getObject method.
Concerning the isFull method, you can check if the size of your ObjectList class is equal to the size it was instantiated with
if(this.size() == this.length){
return true
}
return false;
And getTotal
public int getTotal(){
return this.size();
}

Related

compareTo with objects returns a false while it is true

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.

How to validate a specific type and make my list "type-safe"

I'm trying to create a custom list, that ensures that only one type of reference can be added in my list, i'm trying to make it "type-safe".
The array is already set to an Object type, and everything inherits from Object so how do I substitute/subtype? For example if I want this list to ONLY be able to take String objects. Currently, my program can take both Integer type and String type as seen in the main method.
I can't use generics for this unfortunately.
MyArrayList
import java.util.ArrayList;
public class MyArrayList implements MyList {
private Object[] theList;
private Object type;
public MyArrayList() {
theList = new Object[0];
}
public MyArrayList(Object type) {
theList = new Object[0];
setType(type);
}
public Object getType() {
return type;
}
public void setType(Object type) {
if (type == Integer.class || type == String.class || type == Double.class) {
this.type = type;
} else {
System.out.println("Invalid value");
}
}
public boolean add(Object toAdd) {
if (toAdd != null && toAdd == type.getClass()) {
Object[] temp = new Object[theList.length + 1];
for (int index = 0; index < theList.length; index++) {
temp[index] = theList[index];
}
temp[theList.length] = toAdd;
theList = temp;
return true;
} else {
System.out.println("Invalid type");
return false;
}
}
public Object get(int index){
if(index >= 0 && index < theList.length) {
return theList[index];
} else {
return null;
}
}
public Object remove(int index) {
if (index >= 0 && index < theList.length) {
Object[] newList = new Object[theList.length - 1];
int j = 0;
for (int i = 0; i < theList.length; i++) {
if (i == index) {
continue;
}
newList[j++] = theList[i];
}
theList = newList;
return newList;
}
return null;
}
public int size(){
return theList.length;
}
public boolean isEmpty(){
if(theList.length > 0) {
return true;
} else {
return false;
}
}
public void display() {
for(Object thing: theList) {
System.out.print(thing + ", ");
}
System.out.println();
}
}
MyList
/**
* Write a description of interface List here.
*
* #author (your name)
* #version (a version number or a date)
*/
public interface MyList
{
/**
* Adds a new element at the end of the list.
* #param the object to add
* #return true if element successfully added, otherwise false
*/
boolean add(Object toAdd);
/**
* Gets the object at the specified index.
* #param index value of object to get
* #return object at that index
*/
Object get(int index);
/**
* Removes specified object from list.
* #param index value of object to remove
* #return the object removed
*/
Object remove(int index);
/**
* Returns size of the list
* #return number of elements in the list
*/
int size();
/**
* #return true if the list has no elements, false otherwise
*/
boolean isEmpty();
}
Main
import com.sun.jdi.IntegerType;
public class Main {
public static void main(String[] args) {
Object list = new Object();
Object myList = new MyArrayList(list);
MyArrayList newList = new MyArrayList(myList);
newList.add(2);
newList.add("Tom");
newList.add(0.0);
newList.display();
Without using generics, you can't achieve compile-time type safety for this. But you can cause an exception to be raised at runtime if you create the array dynamically with a component type that is not java.lang.Object, with
public class MyArrayList implements MyList {
private Object[] theList;
public MyArrayList(Class<?> type) {
this.theList = (Object[]) java.lang.reflect.Array.newInstance(type, 10);
}
...
This way, if the class passed to create the array is String.class, then adding an integer to it would result in a java.lang.ArrayStoreException being thrown, and you can try/catch this exception wherever this.theList[n] = object is.
It's worth mentioning, though, that the correct way to do this is to use generics both in your class and in caller classes.
You could create a self-made double linked list by creating a class that is an element in your list that holds the previous element and the following element of the list. Each of these elements could have one parameter, that is of the specific type you want to safe.
Well, without generics you'll have to do all type-checking yourself, and casting at the call site cannot be avoided.
You could, for example, accept a class Object of the desired type in the constructor, and check that all added Objects are instances of that type:
public class MyArrayList implements MyList {
private Object[] theList;
private final Class type;
// I've omitted the generic wildcard here, cause "no generics"
// Suppress wildcard warnings here if needed
// never do this in real, post-Java5 code
public MyArrayList(Class genericType) {
//check any preconditions you want on the class
this.type = genericType;
this.theList = new Object[0];
}
public void add(Object toAdd) {
// omitted code for growing the array here
this.temp[theList.length] = this.type.cast(toAdd); //throws Exception on type mismatch
}
}
This uses Class.cast which throws a ClassCastException on mismatch. You could also just use Class.isInstance to check the tyoe and decide yourself what to do (e.g. throw a different exception).
Note that your setType would be a bad idea, because once you've got that, you can no longer be sure that the values in the array are actually of that type. You'd have to clear the array when setting the type, which makes the method useless - at that point you can just create a new instance.

How can I compare 2 LinkedLists but taking Object as parameter?

This is my school assignment. I don't know how to solve it because the method equals only allows passing one parameter. Please giving me some hints.
Here is the question:
Add the method public boolean equals(Object other) that returns true when the contents of 2 AList objects are the same. Note that 2 AList objects are the same if they have the same number of items and each item in one object is equal to the item in its corresponding location in the other object (15 points).
The method above must be added in LList2.java
AList class
public class AList<T> implements ListInterface<T> {
private T[] list; // array of list entries
private int numberOfEntries;
private static final int DEFAULT_INITIAL_CAPACITY = 25;
public AList() {
this(DEFAULT_INITIAL_CAPACITY); // call next constructor
} // end default constructor
public AList(int initialCapacity) {
numberOfEntries = 0;
// the cast is safe because the new array contains null entries
#SuppressWarnings("unchecked")
T[] tempList = (T[]) new Object[initialCapacity];
list = tempList;
} ......
LList2.java
public class LList2<T> implements ListInterface<T> {
private Node firstNode; // head reference to first node
private Node lastNode; // tail reference to last node
private int numberOfEntries;
public LList2() {
clear();
} // end default constructor
public final void clear() // NOTICE clear is not final in interface and that is OK
{
firstNode = null;
lastNode = null;
numberOfEntries = 0;
} ......
It's an instance method - it compares the object passed as a parameter with the object it's being called on (aka this). Note that you don't explicitly need to call this, but I left it in there to make the code clearer:
#Override
public boolean equals(Object other) {
// Check that other is even an AList
if (!(other instanceof AList)) {
return false;
}
// If it is, cast it and compare the contents:
AList otherAList = (AList) other;
// Compare the lenghts of the arrays
if (this.numberOfEntires != otherAList.numberOfEntries) {
return false;
}
// Compare the contents of the arrays:
for (int i = 0; i < this.numberOfEntries; ++i) {
if (!this.list[i].equals(otherAList.list[i])) {
return false;
}
}
// Didn't find a reason why the two aren't equal, so they must be:
return true;
}

Get item index within an ArrayList by passing generic params

I need to create a method that return the index of an object in a list by comparing one of its fields.
I have 2 classs A and B with overrided Equals() and HashCode() methods like this:
Class A:
public class A {
private String field1;
private String field2;
//getters and setters
#Override
public boolean equals (Object o){
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
A that = (A) o;
return field1.equals(that.field1);
}
#Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + field1.hashCode();
return result;
}
}
Class B :
public class B {
private String field1;
private String field2;
//getters and setters
#Override
public boolean equals (Object o){
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
B that = (B) o;
return field2.equals(that.field2);
}
#Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + field2.hashCode();
return result;
}
}
In my main program I need to implement a generic method that returns the index of an item within an ArrayList<> of A or B.
private int getObjectIndexFromList(List<A or B> list, A or B param){
int index;
try{
index = list.indexOf(list.stream().filter(e -> e.equals(param)));
}catch (NoSuchElementException ex){
index = -1;
}
return index;
}
So my question is how to pass generic params for the method ?
I'm assuming you want to compare with either A.field1, A.field2, B.field1, or B.field1?
In that case you can use a lambda to find it in the stream. Like this:
private <T> int getObjectIndexFromList(List<T> list, Predicate<T> predicate){
int index;
try {
index = list.indexOf(list.stream()
.filter(predicate)
.findFirst()
.get());
} catch (NoSuchElementException ex){
index = -1;
}
return index;
}
Then you just use it like this:
int index = getObjectIndexFromList(listOfAs, a -> a.field1.equals("foo"));
Using streams here isn't optimal though since you're effectively traversing the list twice and checking equality on both the parametar and the sought object. Using a list iterator that keeps track of the current index is be more efficient:
private <T> int getObjectIndexFromList(List<T> list, Predicate<T> predicate){
ListIterator<T> it = list.listIterator();
while (it.hasNext()) {
// Get the item and it's index in the list
int index = it.nextIndex();
T item = it.next();
if (predicate.test(item)) {
// We found it, return the index
return index;
}
}
// We didn't find anything
return -1;
}
Here's an example of it in use:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("foobar");
list.add("fubar");
list.add("Hello World!");
System.out.printf("String with length %s has index %s%n",
5, getObjectIndexFromList(list, s -> s.length() == 5));
}
And the output:
String with length 5 has index 3
If you have override hashcode and equals methods... why don't you make a plain call to 'List.indexOf'?
Make them extend the same abstract class (I don't know the exact problem, but if they have end in the same List is highly probable that they will end being family) and use it.
IndexOf uses 'equals' to find the index of the object so it must work...

Selection Sorting with ArrayLists

I have an arrayList of Students in my main class called S... of objects type student. In "s", i need to sort my Students in my arrayList "S" by the registrationNumber they have, smaller to higher.
I tried many ways, but cannot get it to work...
public static void sort(){
int small;
for (int i=0; i < s.size() -1;i++){
small = i;
for (int ind = i + 1; ind< s.size(); ind++ ){
if( stud.get(ind).getRegNum() < s.get(small).getRegNum() ){
small = ind;
swap(i, small);
}
}
}
}
public static void swap(int one,int two){
}
You should check out java collections.
see http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html
I assume that your student class has a public variable registrationNumber
public class StudentComparator implements Comparator<Student>{
#Override
public int compare(Student o1, Student o2) {
return (o1.registrationNumber>o2.registrationNumber);
}
}
somewhere call:
Collections.sort(students, new StudentComparator ());
Call Collections.sort(yourStudentList);
Your student class have to implement the interface Comparable
Override the comparteTo() method of the interface.
That's it!
Example for a comparator(assume registrationNumber is an integer):
#Override
public int compareTo(Student o) {
if(null== o)
return 1;
if(registrationNumber == 0 && o.registrationNumber==0)
return 0;
if(registrationNumber == 0 && o.registrationNumber!=0)
return -1;
if(registrationNumber != 0 && o.registrationNumber==0)
return 1;
return o.registrationNumber.compareTo(registrationNumber);
}
return 1 //when o is less than this
return -1 //when o is bigger than this
return 0 //when they are equal
EDIT If you need to use selectionsort, than you need this comparator too and the interface compareable. But then you only have so creat a custom sort() function which implements the selectionsort algorithm.

Categories

Resources