I have this class which consists in a group that can contain Circle and Triangle.
public class FiguresGroup {
private static final int NUM_FIGURES = 10;
private Figure[] figuresList = new Figure[NUM_FIGURES];
private int numF = 0;
public void add(Figure f) { figuresList[numF++] = f; }
public String toString() {
String s = "";
for (int i = 0; i < numF; i++) {
s += "\n" + figuresList[i];
}
return s;
}
private boolean found(Figure f) {
for (int i = 0; i < numF; i++) {
if (figuresList[i].equals(f)) return true;
}
return false;
}
private boolean included(FiguresGroup g) {
for (int i = 0; i < g.numF; i++) {
if (!found(g.figuresList[i])) return false;
}
return true;
}
private boolean equals(FiguresGroup g) {
if (g.included(this) && this.included(g)) return true;
}
I don't know how I can implement equals. I tried what you see here but it doesn't work.
For 2 groups to be equal one has to contain every element from the other and vice versa. How to make this work?
You missed a condition on numF of the two objects,
and the equals implementation has a compilation error.
Also note that the found method (depended upon by included) depends on correct implementation of Figure.equals.
If it's correctly implemented, then FiguresGroup.equals could be fixed this way:
private boolean equals(FiguresGroup g) {
return numF == g.numF && g.included(this) && this.included(g);
}
Also, FiguresGroup.equals doesn't override Object.equals, which is confusing. In fact, you're probably already confused by this. When you call figuresGroup.equals outside this class, the code compiles,
even though this method is private,
because actually Object.equals will be called instead of this private method.
You can fix that by overriding Object.equals:
#Override
public boolean equals(Object obj) {
if (!(obj instanceof FiguresGroup)) {
return false;
}
FiguresGroup other = (FiguresGroup) obj;
return numF == other.numF && other.included(this) && this.included(other);
}
Related
I created a HashMap that uses a customed class Location as keys.
After inserting all the entries into the HashMap using put(), I am not able to search the keys.
I have tried to use get() or containsKey() to search, but neither give me positive results. However, I am sure that the keys do exists in the code because I have used HashMap iteration to print out the keys.
Below is the code:
public HashMap<Location, Integer>beenTo = new HashMap<>();
public int uniquePathsIII(int[][] grid) {
for (int i=0; i<grid.length; i++){
for (int j=0; j<grid[0].length; j++){
if (grid[i][j] == 0 || grid[i][j] == 2){
Location newSquare = new Location(i,j);
notBeen.put(newSquare, 1);
}
}
}
Location newSquare = new Location(0,1);
if (notBeen.get(newSquare) != null){
return 10;
}
if (notBeen.isEmpty()){
return -1;
}
}
Below is the class Location:
class Location{
int i; // row
int j; // column
public Location(int _i, int _j){
i = _i;
j = _j;
}
public int getI(){
return i;
}
public int getJ(){
return j;
}
public void setI(int _i){
i = _i;
}
public void setJ(int _j){
j = _j;
}
}
In the above code, I wanted to search for the key Location(0,1). I have made sure that the Hashmap notBeen is not empty, and tried that the key does exist. But I am never able to find it using containsKey() nor get().
You need to implement/override hashCode and equals methods if you want a custom Object to work as a key in a HashMap in Java.
FYI:
_variableName goes against Java naming conventions Oracle Java Naming Convention. It is also not necessary as you can get the same result using:
public Location(int i, int j){
this.i = i;
this.j = j;
}
In order to avoid memory leaks map's key must be immutable object,and improve search key speed,the key object has equals() and hashcode() methods is good practice(first use hashcode judge equals then use equals() method).In your code it is best to make location immutable(not support setter methods).
public class Location {
private final int i;
private final int j;
public Location(int x, int y) {
this.i = x;
this.j = y;
}
public int getI() {
return i;
}
public int getJ() {
return j;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Location)) {
return false;
}
Location point = (Location) o;
return i == point.i &&
j == point.j;
}
#Override
public int hashCode() {
return Objects.hash(i, j);
}
}
So I have a database called appleList. Within it I have apple objects which within them has a list of items. I'm attempting to create a method where it returns true if item j is within the list of customer r and false if its not. This is what I have come up with so far...
public boolean (String m)
{
if(n[i] = p)
found = true;
return found;
}
Use equals() to compare Strings. Also, if n is an array you need to pass it in like below
public boolean hasProduct(String[] n, String p)
{
boolean found = false;
for(int i=0; i < n.size(); i++)
if(n[i].equals(p))
found = true;
return found;
}
There's an existing method in List that you can use
customerList.contains(object)
This method return true if the list contains the object
If you are using a custom object you can override the method equals, so the method above will use it to compare all objects in your list
public class MyCustomClass{
private Integer id;
//Other variables, getters and setters
#Override
public boolean equals(Object o2){
if(o2 instanceof MyCustomClass){
MyCustomClass o2custom = (MyCustomClass) o2;
if(o2custom.getId()!=null && this.id != null){
return o2custom.getId() == this.id;
}
}
return false;
}
}
Hugs
String n is not an array n[0] is wrong try this :
public boolean hasProduct(String p)
{
boolean found = false;
for(int i=0; i < customerList.size(); i++)
if(customerList.get(i) == p)
found = true;
return found;
}
To iterate an ArrayList you need to use .get(). Also, I added a break in your loop once the item is found.
public boolean hasProduct(String n, String p)
{
boolean found = false;
for(int i=0; i < this.customerList.size(); i++)
if(this.customerList.get(i) == p)
found = true;
break;
return found;
}
Since you're looking for a String in an ArrayList, you can simply do something like this:
public boolean hasProduct(ArrayList customerList, String p)
{
return customerList.contains(p);
}
As #DigaoParceiro mentions, if you're looking for a custom object within your collection, be sure to override equals() and hashCode(). String already provides this for you.
My Java assignment is to implement a set class by using an array.
The assignment won't allow me import the set class from the library, so I have to make it on my own. When I tried to print out the array, it prints out numbers in repeats, not unique numbers. I don't know where the problem is, so if you guys can find any errors in my code, it would be great. I tried to add numbers 2, 3, and 4 to the set, so the result should be 2 3 4, but the code shows me 2 3 2 3 2.
I think the source of the problem is from the add method from the set class, but I don't know what the problem is exactly.
import java.util.Arrays;
public final class Set implements SetInterface
{
private int[] set;
private int size;
private int capacity;
public Set(int c)
{
capacity = c;
set = new int[capacity];
size = 0;
}
public boolean contains(int x)
{
boolean contains = false;
for(int i = 0; i<capacity; i++)
{
if(x == set[i])
contains = true;
else
contains = false;
}
return contains;
}
public void add(int x)
{
for(int i = 0; i<capacity; i++)
{
if(!contains(x))
{
if(size == capacity)
{
set = Arrays.copyOf(set,size*2);
}
if(set[i]==0)
{
set[i++] = x;
}
}
}
size++;
}
public boolean remove(int x)
{
boolean remove = false;
for(int i = 0; i < capacity; i++)
{
if(x == set[i])
{
set[i] = set[size -1];
size--;
remove = true;
}
if(isEmpty())
{
remove = false;
}
}
return remove;
}
public void clear()
{
set = null;
size = 0;
}
public int size()
{
return size;
}
public boolean isEmpty()
{
if(size == 0)
return true;
else
return false;
}
public int[] toArray()
{
return Arrays.copyOf(set, capacity);
}
}
This is the driver class that I test my class.
import java.util.Arrays;
public class SetDriver
{
public static void main(String[] args)
{
SetDriver driver = new SetDriver();
Set s1 = new Set(5);
s1.add(2);
s1.add(3);
s1.add(4);
driver.print(s1);
System.out.println("Size: "+s1.size());
}
public static void print(Set s)
{
for(int i = 0; i<s.toArray().length; i++)
{
System.out.print(s.toArray()[i]+" ");
}
System.out.println("");
}
}
The outputs are here:
2 3 2 3 2
Size: 3
There's a likely problem with your contains method. Suppose that you did find a duplicate. What happens is that you assign your variable to true and you continue to iterate. This stomps over the logic entirely; you could have a duplicate but never act on it because your boolean code precludes you from doing so.
Ideally, when you find a match, you must stop iterating and return immediately.
public boolean contains(int value) {
for(int setItem : set) {
if(setItem == value) {
return true;
}
}
return false;
}
You should change add method like this.
public void add(int x) {
if (contains(x))
return;
if (size >= capacity) {
capacity *= 2;
set = Arrays.copyOf(set, capacity);
}
set[size++] = x;
}
I am using a SparseIntArray and I am puzzled by this behavior:
public static SparseIntArray getArray()
{
SparseIntArray result = new SparseIntArray();
result.append(0, 99);
result.append(1, 988);
result.append(2, 636);
return result;
}
public static void testArray()
{
SparseIntArray first = getArray();
SparseIntArray second = getArray();
if( first.equals(second) )
{
Log.v(TAG,"first "+first.toString()+" == second "+second.toString());
}
else
{
Log.v(TAG,"first "+first.toString()+" != second "+second.toString());
}
}
Output:
11-06 14:53:15.011: V/fileName(6709): first {0=99, 1=988, 2=636} != second {0=99, 1=988, 2=636}
I know that using == between two objects will compare the object addresses, which in this case are different, but here I am using SparseIntArray.equals(Object other) and the intended result is not unexpected.
I am sure I can roll my own compare method, but it sounds kind of silly. What is the point of having a base class Object.equals(Object other) method if we cant rely on it?
Can someone point to any mistake?
I just searched for the code of SparseIntArray. If you are referring to android.util.SparseIntArray, it doesn't override equals, which means it uses the default implementation of Object class, which compares the references.
What is the point for having a base class Object.equals(Object other) method if we cant rely on it?
Actually, you can't rely of the base class Object.equals, since it does precisely what you don't want to do:
public boolean equals(Object obj)
{
return (this == obj);
}
It's up to the writers of any class to decide whether to override equals and give a different implementation.
#Eran is right, Object.equals(Object) does not cut it.
I have made a simple static method to compare two instances
public static boolean compareSame( SparseIntArray first, SparseIntArray second )
{
// compare null
if( first == null )
{
return (second == null);
}
if( second == null )
{
return false;
}
// compare count
int count = first.size();
if( second.size() != count )
{
return false;
}
// for each pair
for( int index = 0; index < count; ++index )
{
// compare key
int key = first.keyAt(index);
if( key != second.keyAt(index))
{
return false;
}
// compare value
int value = first.valueAt(index);
if( second.valueAt(index) != value)
{
return false;
}
}
return true;
}
I will probably end up deriving my own version of SparseIntArray and override the equals method, I think this is more clean.
[EDIT] Here is the code for an sub-class implementing equals
import android.util.SparseIntArray;
public class SparseIntArrayComparable extends SparseIntArray {
#Override
public boolean equals( Object obj ) {
if( obj instanceof SparseIntArray ) {
SparseIntArray other = (SparseIntArray)obj;
// compare count
int count = size();
if( count != other.size() )
return false;
// for each pair
for( int index = 0; index < count; ++index ) {
if( keyAt(index) != other.keyAt(index))
return false;
if( valueAt(index) != other.valueAt(index) )
return false;
}
return true;
}
else
return false;
}
}
Consider you have been told to implement a kind of the java String.substring method.
The signature of the method is as follows:
public static boolean isSubstring(String i_StringForSearch, String i_SubStringToFind)
Here is my solution, but I feel it's still not the best elegant solution I could have.(Many canonical if else's)
What do you think? Would you do it in another way?
public static boolean isSubstring(String i_StringForSearch, String i_SubStringToFind)
{
int strForSearchIndex = 0;
int subStrToFindIndex = 0;
boolean endOfStringToSearch = false;
boolean foundSubString = false;
boolean isThereASequenceOfMatching = false;
while(!endOfStringToSearch && !foundSubString)
{
if(strForSearchIndex == i_StringForSearch.length())
{
endOfStringToSearch = true;
}
else if(i_StringForSearch.charAt(strForSearchIndex) == i_SubStringToFind.charAt(subStrToFindIndex))
{
isThereASequenceOfMatching = true;
if(subStrToFindIndex == i_SubStringToFind.length() -1 )
{
foundSubString = true;
}
subStrToFindIndex++;
strForSearchIndex++;
}
else if(i_StringForSearch.charAt(strForSearchIndex) != i_SubStringToFind.charAt(subStrToFindIndex))
{
if(isThereASequenceOfMatching)
{
subStrToFindIndex = 0;
isThereASequenceOfMatching = false;
}
strForSearchIndex++;
}
}
return foundSubString;
}
Look up the Boyer-Moore and Knuth-Morris-Pratt algorithms. In tests many years ago I found BM to be slightly faster.
public static boolean isSubstring(final String i_StringForSearch, final String i_SubStringToFind) {
int j = 0;
for (int i = 0; i < i_StringForSearch.length(); i++) {
if (i_StringForSearch.charAt(i) == i_SubStringToFind.charAt(j)) {
j++;
if (j == i_SubStringToFind.length()) {
return true;
}
}
}
return false;
}