Set Implementation Equals Method Always returns false - java

One of my methods is not working in my Java implementation of the Set class. Why does equals always return false?
public boolean equals(Set<E> s) {
if(this.size() == s.size()){
for(int i = 0; i < size(); i++){
if(theData[i] == s.get(i)){
return true;
}
}
}
return false;
}
My set is Set<Integer> and I've compared a set of (1,2,3,4) and (1,2,3,4) together and it outputs false.
EDIT: All of my sets are ordered from least to greatest.
EDIT2: Here is my code dealing with equals in the main driver
else if(spaceSplit[0].equals("equal")){
if(spaceSplit.length == 3){
String fSet = spaceSplit[1];
String sSet = spaceSplit[2];
int fSetIndex = 0;
int sSetIndex = 0;
for(int i = 0; i < sets.size(); i++){
if(((Set<Integer>) sets.get(i)).getName().equals(fSet)){
fSetIndex = i;
}
}
for(int i = 0; i < sets.size(); i++){
if(((Set<Integer>) sets.get(i)).getName().equals(sSet)){
sSetIndex = i;
}
}
System.out.println(sets.get(fSetIndex).equals(sets.get(sSetIndex)));
} else {
System.out.println("Parameters entered wrong, please try again.");
}
EDIT3: In my program I've been messing with it, and it outputs false everytime I put a real set in. If I just made up 2 sets that don't exist and call the equals method, it outputs true. I'm so confused.
EDIT4: Here's more of the set code:
import java.util.*;
public class Set<E extends Comparable> {
private String name;
private int size = 0;
private E[] theData;
private static final int INITIAL_CAPACITY = 100;
private int capacity = 0;
public Set() {
capacity = INITIAL_CAPACITY;
theData = (E[]) new Integer[capacity];
}
public Set(String name) {
this.name = name;
capacity = INITIAL_CAPACITY;
theData = (E[]) new Integer[capacity];
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private void reallocate() {
capacity = 2 * capacity;
}

Your problem is you aren't overriding equals()
The signature is not
public boolean equals(Set<E>)
It is
public boolean equals(Object)
That is why when you add the #Override annotation you get a compiler error. You must use Object as the parameter, then check for instanceof and cast.

The compare should be .equals instead of ==.

try like this:
public boolean equals(Set<E> s) {
if(this.size() == s.size()){
for(int i = 0; i < size(); i++){
if(!this.get(i).equals(s.get(i))){
return false;
}
}
return true;
}
return false;
}

Related

Generic Linear List based on Arrays

I'm trying to write a Linear List based on arrays, but make the list be able to store any value by using Java Generics. This way I can create other programs that utilize it, but pass in different data types. I'm not entirely sure how to do this, any help would be appreciated.
I guess Im struggling trying to set it up and create the functions. The generic type really messes me up.
For example, trying to add a removeFirst() function, I cant use a loop like this:
for (int i = 0; i < n - 1; i++)
newList[i] = newList[i + 1];
— as it says The type of the expression must be an array type but it resolved to ArrayList.
Fair warning, I'm still learning data structures. This is what I have so far:
import java.util.ArrayList;
public class LinearList<T> {
private static int SIZE = 10;
private int n = 0;
private final ArrayList<T> newList = new ArrayList<T>(SIZE);
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
public void add(T value, int position) {
newList.add(position, value);
n++;
}
public void addFirst(T value) {
newList.add(0, value);
n++;
}
public void removeLast() {
T value = null;
for (int i = 0; i < newList.size(); i++)
value = newList.get(i);
newList.remove(value);
n--;
}
public void removeFirst() {
newList.remove(0);
n--;
}
public T first() {
return newList.get(0);
}
public T last() {
int value = 0;
for (int i = 0; i < newList.size() - 1; i++)
value++;
return newList.get(value);
}
public int count() {
return n;
}
public boolean isFull() {
return (n >= SIZE);
}
public boolean isEmpty() {
return (n <= 0);
}
//part 4
public void Grow() {
int grow = SIZE / 2;
SIZE = SIZE + grow;
}
public void Shrink() {
int grow = SIZE / 2;
SIZE = SIZE - grow;
}
public String toString() {
String outStr = "" + newList;
return outStr;
}
}
A good start would be to make it non-generic with a class you are comfortable with, such as an Integer.
Once you have it set up, you can then make it generic by adding <T> to the class name, then replacing all references of Integer with T.
public class MyArray{ becomes public class MyArray<T>{
public Integer add(Integer value){ becomes public T add(T value){
See What are Generics in Java? for more help

Writing an equals method to compare two arrays

I have the following code, I believe something is off in my equals method but I can't figure out what's wrong.
public class Test {
private double[] info;
public Test(double[] a){
double[] constructor = new double[a.length];
for (int i = 0; i < a.length; i++){
constructor[i] = a[i];
}
info = constructor;
}
public double[] getInfo(){
double[] newInfo = new double[info.length];
for(int i = 0; i < info.length; i++){
newInfo[i] = info[i];
}
return newInfo;
}
public double[] setInfo(double[] a){
double[] setInfo = new double[a.length];
for(int i = 0; i < a.length; i++){
setInfo[i] = a[i];
}
return info;
}
public boolean equals(Test x){
return (this.info == x.info);
}
}
and in my tester class I have the following code:
public class Tester {
public static void main(String[] args) {
double[] info = {5.0, 16.3, 3.5 ,79.8}
Test test1 = new Test();
test 1 = new Test(info);
Test test2 = new Test(test1.getInfo());
System.out.print("Tests 1 and 2 are equal: " + test1.equals(test2));
}
}
the rest of my methods seem to function correctly, but when I use my equals method and print the boolean, the console prints out false when it should print true.
You are just comparing memory references to the arrays. You should compare the contents of the arrays instead.
Do this by first comparing the length of each array, then if they match, the entire contents of the array one item at a time.
Here's one way of doing it (written without using helper/utility functions, so you understand what's going on):
public boolean equals(Test x) {
// check if the parameter is null
if (x == null) {
return false;
}
// check if the lengths are the same
if (this.info.length != x.info.length) {
return false;
}
// check the elements in the arrays
for (int index = 0; index < this.info.length; index++) {
if (this.info[index] != x.info[index]) {
return false;
} Aominè
}
// if we get here, then the arrays are the same size and contain the same elements
return true;
}
As #Aominè commented above, you could use a helper/utility function such as (but still need the null check):
public boolean equals(Test x) {
if (x == null) {
return false;
}
return Arrays.equals(this.info, x.info);
}

Java counter not counting properly

Hi I'm very new to Java and have this HW problem, we are asked to build Class LTile, a tile in the game of Scrabble.
The ID number of a tile should be assigned by a class/static data member, which keeps track of the number of LTile objects produced.
My ID output didn't not print from 1 to 26, instead, they are all assign 26.
I suspect my ID attribute must be wrong, but couldn't figure out the exactly error. Any help is greatly appreciated! Thanks!
package hw2;
public class LTile {
char letter;
private int value;
private static int ID=0;
public LTile(){
this.letter = '?';
this.value = 0;
LTile.ID++;
}
public LTile(char letter, int value){
this.letter=letter;
this.value=value;
LTile.ID++;
}
public char getLetter(){
return this.letter;
}
public int getValue(){
return this.value;
}
public int getID(){
return LTile.ID;
}
public boolean equals(Object obj){
if(this ==obj){
return true;}
else{
return false;
}
}
public String toString(){
return "["+ID+":" + letter+","+value+"]";
}
//**
//** main() for testing LTile
//**
public static void main(String[] args)
{
final String letters = "EAIONRTLSUDGBCMPFHVWYKJXQZ";
final int[] values = {1,1,1,1,1,1,1,1,1,1,2,2,3,3,3,3,4,4,4,4,4,5,8,8,10,10};
java.util.List<LTile> lst = new java.util.ArrayList<LTile>();
for (int i = 0; i < letters.length(); ++i)
lst.add(new LTile(letters.charAt(i), values[i]));
for (LTile tile : lst)
System.out.println(tile);
System.out.println();
// test for equals
boolean found = false;
for (int i = 0; i < lst.size()-1; ++i) {
for (int j = i+1; j < lst.size(); ++j) {
if (lst.get(i).equals(lst.get(j))) {
System.out.println("ERROR in equals() found for "
+ lst.get(i) + " and " + lst.get(j));
found = true;
}
}
}
if (!found)
System.out.println("No error in equals().");
}
}
My output is:
[26:E,1]
[26:A,1]
[26:I,1]
[26:O,1]
[26:N,1]
[26:R,1]
[26:T,1]
[26:L,1]
[26:S,1]
[26:U,1]
[26:D,2]
[26:G,2]
[26:B,3]
[26:C,3]
[26:M,3]
[26:P,3]
[26:F,4]
[26:H,4]
[26:V,4]
[26:W,4]
[26:Y,4]
[26:K,5]
[26:J,8]
[26:X,8]
[26:Q,10]
[26:Z,10]
No error in equals()
**The correct output should be:**
[1: E,1]
[2: A,1]
[3: I,1]
[4: O,1]
[5: N,1]
[6: R,1]
[7: T,1]
[8: L,1]
[9: S,1]
[10: U,1]
[11: D,2]
[12: G,2]
[13: B,3]
[14: C,3]
[15: M,3]
[16: P,3]
[17: F,4]
[18: H,4]
[19: V,4]
[20: W,4]
[21: Y,4]
[22: K,5]
[23: J,8]
[24: X,8]
[25: Q,10]
[26: Z,10]
No error in equals().
The ID number of a tile should be assigned by a class/static data member, which keeps track of the number of LTile objects produced.
This means that the id value should come from a static data member, not that it should be a static data member. So you need two fields: an instance id field to keep the object's id and a static CURRENT_ID field to keep track of how many objects you have created so far.
public class LTile {
char letter;
private int value;
private int id; // instance id
private static int CURRENT_ID = 0; // static counter from where the instance ids will be drawn
public LTile() {
// Call the other constructor to avoid unnecessary repetition
this('?', 0);
}
public LTile(char letter, int value) {
this.letter = letter;
this.value = value;
this.id = LTile.CURRENT_ID++;
}
// rest of the code
public int getID() {
return this.id;
}
public String toString() {
return "["+this.id+":" + this.letter+","+this.value+"]";
}
}
Note you also need to change getId() and toString() to use the instance id instead of the static counter.

returning the position of an array

I am trying to create a find method, that will check every entry in my PhoneDirectory, and return the position of the name that matches the name given in the parameter. This is what currently have:
private String find(String name) {
for (DirectoryEntry x : theDirectory) {
if (x.getName().equals(name)) {
return x.getName();
}
}
return null;
}
However I will be calling my find function from within other methods that don't necessarily want the name returned, but instead the number attached to the name, (each DirectoryEntry has a name and a telno).
Any help regarding how to return the position of the array instead of just the matching name, would be much appreciated.
you can take a couter to count the postion
private int find(String name) {
int i = 0;
for (DirectoryEntry x : theDirectory) {
if (x.getName().equals(name)) {
return i;
}
i++;
}
return -1; // returning -1 if not found
}
or you can use normal for loop instead of foreach
private String find(String name) {
int k=0;
for (DirectoryEntry x : theDirectory) {
if (x.getName().equals(name)) {
k++;
return x.getName();
}
}
//k will give you pos
return null;
}
If you want the position in the array, use a regular loop instead of a foreach loop.
for (int i=0;i<theDirectory.length;i++) {
DirectoryEntry x = theDirectory[i];
if (x.getName().equals(name)) {
return i;
}
}
Depending on the type of your theDirectory-field you could use an own counter up to its length:
private int find(String name) {
for (int i = 0; i < theDirectory.length(); i++) {
DirectoryEntry x = theDirectory[i]; //If it is an Array; for Lists use get etc...
if (x.getName().equals(name)) {
return i;
}
}
return -1;
}
Why not to avoid reinventing the wheel and use Guava instead:
private int find(String name) {
return Iterables.indexOf(theDirectory, new Predicate<DirectoryEntry>() {
public boolean apply(DirectoryEntry de) {
return de.getName().equals(name);
}
});
}

Algorithm course: Output of int sort and method to sort Strings

My assignment asks me to make a TV show program, where I can input shows, delete, modify and sort them. What I'm stuck on is the sorting part. With the show, it asks for the name, day a new episode premieres, and time. Those are the keys I need to sort it by.
The program prompts the user to input one of those keys, then the program needs to sort (sorting by day will sort alphabetically).
I made a class and used an array. Here is the class:
public class showInfo
{
String name;
String day;
int time;
}
And the method to sort by time in the code:
public static void intSort()
{
int min;
for (int i = 0; i < arr.length; i++)
{
// Assume first element is min
min = i;
for (int j = i+1; j < arr.length; j++)
{
if (arr[j].time < arr[min].time)
{
min = j;
}
}
if (min != i)
{
int temp = arr[i].time;
arr[i].time = arr[min].time;
arr[min].time = temp;
}
}
System.out.println("TV Shows by Time");
for(int i = 0; i < arr.length; i++)
{
System.out.println(arr[i].name + " - " + arr[i].day + " - " + arr[i].time + " hours");
}
}
When I call it and output it in the main, it only shows "TV Shows by Time" and not the list. Why is this?
Also, I need to make ONE method that I will be able to use to sort both the day AND the name (both Strings). How can I do this without using those specific arrays (arr[i].name, arr[i].day) in the method?
Any help would be greatly appreciated! Thanks in advance!
In this part of your code
if (min != i) {
int temp = arr[i].time;
arr[i].time = arr[min].time;
arr[min].time = temp;
}
You're just changing the time when you should move the whole object instead. To fix it, the code must behave like this:
if (min != i) {
//saving the object reference from arr[i] in a temp variable
showInfo temp = arr[i];
//swapping the elements
arr[i] = arr[min];
arr[min] = temp;
}
I̶t̶ ̶w̶o̶u̶l̶d̶ ̶b̶e̶ ̶b̶e̶t̶t̶e̶r̶ ̶t̶o̶ ̶u̶s̶e̶ ̶ Arrays#sort ̶w̶h̶e̶r̶e̶ ̶y̶o̶u̶ ̶p̶r̶o̶v̶i̶d̶e̶ ̶a̶ ̶c̶u̶s̶t̶o̶m̶ ̶̶C̶o̶m̶p̶a̶r̶a̶t̶o̶r̶̶ ̶o̶f̶ ̶t̶h̶e̶ ̶c̶l̶a̶s̶s̶ ̶b̶e̶i̶n̶g̶ ̶s̶o̶r̶t̶e̶d̶ ̶(̶i̶f̶ ̶y̶o̶u̶ ̶a̶r̶e̶ ̶a̶l̶l̶o̶w̶e̶d̶ ̶t̶o̶ ̶u̶s̶e̶ ̶t̶h̶i̶s̶ ̶a̶p̶p̶r̶o̶a̶c̶h̶)̶.̶ ̶S̶h̶o̶r̶t̶ ̶e̶x̶a̶m̶p̶l̶e̶:̶
showInfo[] showInfoArray = ...
//your array declared and filled with data
//sorting the array
Arrays.sort(showInfoArray, new Comparator<showInfo>() {
#Override
public int compare(showInfo showInfo1, showInfo showInfo2) {
//write the comparison logic
//basic implementation
if (showInfo1.getTime() == showInfo2.getTime()) {
return showInfo1.getName().compareTo(showInfo2.getName());
}
return Integer.compare(showInfo1.getTime(), showInfo2.getTime());
}
});
//showInfoArray will be sorted...
Since you have to use a custom made sorting algorithm and support different ways to sort the data, then you just have to change the way you compare your data. This mean, in your current code, change this part
if (arr[j].time < arr[min].time) {
min = j;
}
To something more generic like
if (compare(arr[j], arr[min]) < 0) {
min = j;
}
Where you only need to change the implementation of the compare method by the one you need. Still, it will be too complex to create and maintain a method that can support different ways to compare the data. So the best option seems to be a Comparator<showInfo>, making your code look like this:
if (showInfoComparator.compare(arr[j], arr[min]) < 0) {
min = j;
}
where the showInfoComparator holds the logic to compare the elements. Now your intSort would become into something more generic:
public static void genericSort(Comparator<showInfo> showInfoComparator) {
//your current implementation with few modifications
//...
//using the comparator to find the minimum element
if (showInfoComparator.compare(arr[j], arr[min]) < 0) {
min = j;
}
//...
//swapping the elements directly in the array instead of swapping part of the data
if (min != i) {
int temp = arr[i].time;
arr[i].time = arr[min].time;
arr[min].time = temp;
}
//...
}
Now, you just have to write a set of Comparator<showInfo> implementations that supports your custom criteria. For example, here's one that compares showInfo instances using the time field:
public class ShowInfoTimeComparator implements Comparator<showInfo> {
#Override
public int compare(showInfo showInfo1, showInfo showInfo2) {
//write the comparison logic
return Integer.compare(showInfo1.getTime(), showInfo2.getTime());
}
}
Another comparator that uses the name field:
public class ShowInfoNameComparator implements Comparator<showInfo> {
#Override
public int compare(showInfo showInfo1, showInfo showInfo2) {
//write the comparison logic
return showInfo1.getName().compareTo(showInfo2.getName());
}
}
Now in your code you can call it like this1:
if (*compare by time*) {
genericSort(showInfoArray, new ShowInfoTimeComparator());
}
if (*compare by name*) {
genericSort(showInfoArray, new ShowInfoNameComparator());
}
if (*another custom rule*) {
genericSort(showInfoArray, new ShowInfoAnotherCustomRuleComparator());
}
where now you can implement a custom rule like compare showInfo objects using two or more fields. Taking as example your name and day fields (as stated in the question):
public class ShowInfoNameAndDayComparator implements Comparator<showInfo> {
#Override
public int compare(showInfo showInfo1, showInfo showInfo2) {
//write the comparison logic
int nameComparisonResult = showInfo1.getName().compareTo(showInfo2.getName());
if (nameComparisonResult == 0) {
return showInfo1.getDay().compareTo(showInfo2.getDay());
}
return nameComparisonResult;
}
}
1: There are other ways to solve this instead using lot of if statements, but looks like that's outside the question scope. If not, edit the question and add it to show another ways to solve this.
Other tips for your current code:
Declare the names of the classes using CamelCase, where the first letter of the class name is Upper Case, so your showInfo class must be renamed to ShowInfo.
To access to the fields of a class, use proper getters and setters instead of marking the fields as public or leaving the with default scope. This mean, your ShowInfo class should become into:
public class ShowInfo {
private String name;
private String day;
private int time;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
//similar for other fields in the class
}
Use selection sort algorithm which is easy to implement,
for (int i = 0; i < arr.length; i++)
{
for (int j = i + 1; j < arr.length; j++)
{
if (arr[i].time > arr[j].time) // Here ur code that which should be compare
{
ShowInfo temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
no need to check min element. go through this wiki http://en.wikipedia.org/wiki/Selection_sort
Why not you use a Collection for this sort of a thingy to work. Moreover, in your added example, you are simply changing one attribute of a given object, while sorting, though you not changing the position of the object as a whole, inside the given list.
Create a List which will contain the references of all the Shows, now compare each attribute of one Show with another, in the List. Once the algorithm feels like, that swapping needs to be done, simply pick the reference from the List, save it in a temp variable, replace it with a new reference at this location, and set duplicate to the one stored in the temp variable. You are done, List is sorted :-)
Here is one small example for the same, for help :
import java.io.*;
import java.util.*;
public class Sorter {
private BufferedReader input;
private List<ShowInfo> showList;
public Sorter() {
showList = new ArrayList<ShowInfo>();
input = new BufferedReader(
new InputStreamReader((System.in)));
}
private void createList() throws IOException {
for (int i = 0; i < 5; i++) {
System.out.format("Enter Show Name :");
String name = input.readLine();
System.out.format("Enter Time of the Show : ");
int time = Integer.parseInt(input.readLine());
ShowInfo show = new ShowInfo(name, time);
showList.add(show);
}
}
private void performTask() {
try {
createList();
} catch (Exception e) {
e.printStackTrace();
}
sortByTime(showList);
}
private void sortByTime(List<ShowInfo> showList) {
int min;
for (int i = 0; i < showList.size(); i++) {
// Assume first element is min
min = i;
for (int j = i+1; j < showList.size(); j++) {
if (showList.get(j).getTime() <
showList.get(min).getTime()) {
min = j;
}
}
if (min != i) {
ShowInfo temp = showList.get(i);
showList.set(i, showList.get(min));
showList.set(min, temp);
}
}
System.out.println("TV Shows by Time");
for(int i = 0; i < showList.size(); i++) {
System.out.println(showList.get(i).getName() +
" - " + showList.get(i).getTime());
}
}
public static void main(String[] args) {
new Sorter().performTask();
}
}
class ShowInfo {
private String name;
int time;
public ShowInfo(String n, int t) {
name = n;
time = t;
}
public String getName() {
return name;
}
public int getTime() {
return time;
}
}
EDIT 2 :
For sorting By Name you can use this function :
private void sortByName(List<ShowInfo> showList) {
int min;
for (int i = 0; i < showList.size(); i++) {
// Assume first element is min
min = i;
for (int j = i+1; j < showList.size(); j++) {
int value = (showList.get(j).getName()).compareToIgnoreCase(
showList.get(min).getName());
if (value < 0)
min = j;
}
if (min != i) {
ShowInfo temp = showList.get(i);
showList.set(i, showList.get(min));
showList.set(min, temp);
}
}
System.out.println("TV Shows by Time");
for(int i = 0; i < showList.size(); i++) {
System.out.println(showList.get(i).getName() +
" - " + showList.get(i).getTime());
}
}
EDIT 3 :
Added Comparable<?> Interface, to the existing class to perform sorting based on specified input. Though one can improve on the logic, by using Enumeration, though leaving it for the OP to try his/her hands on :-)
import java.io.*;
import java.util.*;
public class Sorter {
private BufferedReader input;
private List<ShowInfo> showList;
private int command;
public Sorter() {
showList = new ArrayList<ShowInfo>();
input = new BufferedReader(
new InputStreamReader((System.in)));
command = -1;
}
private void createList() throws IOException {
for (int i = 0; i < 5; i++) {
System.out.format("Enter Show Name :");
String name = input.readLine();
System.out.format("Enter Time of the Show : ");
int time = Integer.parseInt(input.readLine());
ShowInfo show = new ShowInfo(name, time);
showList.add(show);
}
}
private void performTask() {
try {
createList();
} catch (Exception e) {
e.printStackTrace();
}
System.out.format("How would you like to sort : %n");
System.out.format("Press 0 : By Name%n");
System.out.format("Press 1 : By Time%n");
try {
command = Integer.parseInt(input.readLine());
} catch (Exception e) {
e.printStackTrace();
}
sortList(showList);
}
private void sortList(List<ShowInfo> showList) {
int min;
for (int i = 0; i < showList.size(); i++) {
// Assume first element is min
min = i;
for (int j = i+1; j < showList.size(); j++) {
showList.get(j).setValues(command);
int value = showList.get(j).compareTo(showList.get(min));
if (value < 0) {
min = j;
}
}
if (min != i) {
Collections.swap(showList, i, min);
}
}
System.out.println("TV Shows by Time");
for(int i = 0; i < showList.size(); i++) {
System.out.println(showList.get(i).getName() +
" - " + showList.get(i).getTime());
}
}
public static void main(String[] args) {
new Sorter().performTask();
}
}
class ShowInfo implements Comparable<ShowInfo> {
private String name;
private int time;
private int command;
public ShowInfo(String n, int t) {
name = n;
time = t;
}
public String getName() {
return name;
}
public int getTime() {
return time;
}
public void setValues(int cmd) {
command = cmd;
}
public int compareTo(ShowInfo show) {
int lastCmp = 1;
if (command == 0) {
lastCmp = name.compareTo(show.name);
} else if (command == 1) {
if (time < show.time) {
lastCmp = -1;
} else if (time == show.time) {
lastCmp = 0;
} else if (time > show.time) {
lastCmp = 1;
}
}
return lastCmp;
}
}

Categories