I'm trying to write a method that checks weather all the Objects in an ArrayList have the same value. For example, in the following code list1 should return true, and list2 should return false...
list1=[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]
list2=[1,3,4,2,4,1,3,4,5,6,2,1,5,2,4,1]
What is the best way to write this method? Is there any quick methods to do this, or do I need to manually loop through the values?
So, you need to check if all the values in a list are the same?
boolean checkList(List<Integer> list) {
if (list.isEmpty())
return false;
int value = list.get(0);
for (int i = 1; i < list.size(); ++i) {
if (list.get(i) != value)
return false;
}
return true;
}
but I'd be careful about null values in the list, too...
Related
I have a method that takes an array as a parameter and returns a boolean.
Inside the method, I have an if/else statement. If the statement is true, I want the result to return true, if the statement is false, I want the statement to returns false.
public static boolean allPositive (double[] arr)
{
for (int i = 0; i < arr.length; i++)
{
if(arr[i] > 0)
{
return true;
}
else
{
return false;
}
}
return //What do i put here?
}
}
Of course, it needs a return value at the end. However, I am confused on what I should return at the bottom. How should I rewrite this?
First, your code is wrong. For example, with {1, -1, 2}, your method will return true.
If you write it differently, you avoid the problem :
public static boolean allPositive (double[] arr) {
for (int i = 0; i < arr.length; i++) {
if(arr[i] < 0)
{
return false;
}
}
return true;
}
EDIT : Or even better, a one-line solution with Java 8 and Streams (I like one-line solutions):
public static boolean allPositive (double[] arr) {
//Stream the array and see if any elements matches condition `<0`.
return !Arrays.stream(arr).anyMatch(i->i<0);
}
If you need more than one line of code in order to work with collections, then you should learn about Streams.
public static boolean allPositive (double[] arr)
{
boolean b = true;
for (int i = 0; i < arr.length; i++)
{
if(!(arr[i] > 0))
{
b = false;
}
}
return b;
}
The way Java works, it ensures no problems with your code by making sure all your returns happen outside of the if else statement. This because, a common bug by programmers is to return in the if else statement, but never create an else condition, so the method never returns anything. Doing it this way is more of a good practice thing so you don't bug out later trying to figure out why a method won't return.
The answer by Arnaud has multiple return statements. Code smell. The answer by DreadHeadedDeveloper has a logic error if the array is {1,-1,2}, it returns true.
This function/method is terse and follows good coding practices.
public static boolean allPositive (double[] arr) {
boolean ret = true;
for (int i = 0; i < arr.length; i++) {
if(arr[i] <= 0) {
ret = false;
}
}
return ret;
}
You have to return in the end of the method (after the loop) the value that should be returned if an empty array is passed to your method. It's up to you to decide whether an empty array is "allPositive" or not.
Trying to check if two arrays are equal, meaning same length and same elements in positions.
I've tried Arrays.equals(1,2) but it's still coming out as false, while it needs to be coming out as true.
I've tried to create a nested for loop to check each index but I am still getting false.
My code:
public boolean equals(double[] s) //for loop checking each element
{
if (s==null)
{
return false;
}
for (int i=0;i<data.length;i++)
{
for(int j=0;j<s.length;j++)
{
if (data[i]!=s[j])
{
return false;
}
}
}
return true;
}
Don't reinvent the wheel!
public boolean equals(double[] s) {
return Arrays.equals(s, data);
}
Arrays.equals() compares array lengths and each element.
if you want to see if they have the same elements but you don't care if they have the same order, sort them first.
Arrays.sort(data);
Arrays.sort(s);
return Arrays.equals(data,s);
You don't need a nested loop to check the elements. In fact, your code is wrong in a sense that it's checking all the elements from one array to another.
You might want to
// Check to make sure arrays have same length
if (data.length != s.length)
return false;
for (int i=0;i<data.length;i++)
{
if (data[i]!=s[i])
{
return false;
}
}
return true;
You can use as below :
if(arr1.length!=arr2.length)
return false;
for(int index=0;index<arr1.length;index++)
{
if (arr1[index]!=arr2[index])
return false;
}
return true;
I want to add a method to a class I made that checks whether the two sequences have the same values in the same order.
Here is what I have so far:
public class Sequence {
private int[] values;
public Sequence(int size) { values = new int[size]; }
public void set(int i, int n) { values[i] = n; }
}
public boolean equals (Sequence other)
...??
The first part of the class I think is correct but I'm having a lot of trouble with the method that tests if the values are in the same order. Ideas and feedback would be much appreciated :)
If you want to say wether 2 Sequences are equals, you can override equals method and hashCode to follow contract.
Example using Eclipse tool:
public class Sequence {
private int[] values;
public Sequence(int size) { values = new int[size]; }
public void set(int i, int n) { values[i] = n; }
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(values);
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Sequence other = (Sequence) obj;
if (!Arrays.equals(values, other.values))
return false;
return true;
}
}
Then in a main class you can do the following thing
public static void main(String args[]){
Sequence s = new Sequence(5);
Sequence s2 = new Sequence(5);// new Sequence(4)
s.set(0, 1);
s2.set(0, 1);
System.out.println(s.equals(s2));//will print true
}
You have to take care that if you use my comment code (new Sequence(4)) this will return false and perhaps is not what you want! Then you will have to implement your own equals and not autogenerated by ide.
Arrays have a built in .equals() method: .equals(int[], int[])
Very simple, but hope this helps.
public boolean equals (Sequence other) {
// if sizez are different, automatic false
if (this.getValues().length != other.getValues().length)
return false;
else
int[] array1 = other.getValues();
int[] array2 = this.getValues();
// if any indices are not equal, return false
for (int i = 0; i < other.getValues().length; i++){
if (array1[i] != array2[i])
return false;
}
// it not returned false, return true
return true;
}
First and foremost, you will need to make your .equals() method a member of your Sequence class. Otherwise, you will only have access to one Sequence object.
If you want to check if 2 arrays have the same elements in the same order, all you need to do is compare each element in turn. Is the first element of this one the same as the first element of the other, etc. When you come across a pair of elements that are different, you will be able to return false. Otherwise, you can return true when you have checked each pair of elements.
One issue you may encounter is arrays of different size. Depending on what you're trying to do, you may want to either return false immediately without checking the elements or stop when you reach the end of the shorter array. Based off your question, you probably want the former, but that depends on what problem you are trying to solve.
Your .equals() method will be able to access the values arrays of both this and other even if they aren't public. This is because .equals() as a function of the Sequence class is allowed to access all the members of Sequence, even in Sequence objects other than this.
With this information, you should be able to write your .equals() method.
public boolean equals (Sequence other){
int[] first = this.getValues();
int[] second = other.getValues();
boolean same = true;
if(first.length != second.length){
return false;
}
for(int i = 0; i < first.length; i++){
if(first[i] != second[i]){
return false;
}
}
return same;
}
Note: you will have to make the values array public in the Sequence class or add a getter method to the Sequence class...a getter would be the better option
public class LinkedList {
Object contents;
LinkedList next = null;
public boolean equals(Object item) {
return (this == item) || ((item instanceof LinkedList) && this.equals((LinkedList)item));
}
public boolean equals(LinkedList item) {
return myUtil.equals(this.contents, item.contents) && myUtil.equals(this.next, item.next);
}
}
public class myUtil{
public static boolean equals(Object x, Object y) {
return (x == y) || (x != null && x.equals(y));
}
}
main(){
LinkedList myList = new LinkedList();
myList.next = new LinkedList();
LinkedList head = myList.next;
myList.next = head;
}
I think i have created a circular linkedlist here. So what i have done is to overwrite the equals method to ensure that circular references are handled:
For some reason the LinkedList.equals doesnt seem to return...is it because of my circular linkedlist, or am i missing some conditions?
The primary problem with this code is that your comparison will not terminate upon circular reference, and will loop forever if all contents fields are equal. It will always continue to the next comparison, and since the next item is always there (as it's a circle) this will continue forever.
myUtil.equals(this.contents, item.contents) && myUtil.equals(this.next, item.next);
To solve this issue, the simplest method would be to add a boolean private 'visited' field to each List item. When you compare, set visited on each item after the comparison. If both are not visited and the same, then continue. If only one is visited, your lists are not identical. If both are visited, you've compared the reachable entirety of the list. Generally, having loops in your list are a bad idea, and there exist algorithms specifically to detect them. This can be a confusing topic. Here is a coverage of loop detection that may help you understand the issue further. Remember, if you use the visited field, you must unset all of them with another loop in your equals() to allow it to run again.
On another note, you do not initialize the contents field of your list nodes for the test. This is okay here, since they are initialized to null, but generally it is good practice to explicitly initialize all your fields.
Generally speaking, you also don't need the equals(Object item) override. Try
public boolean equals(LinkedList item){
if (this == item){
return true; // It's the same object
}
// Add some null checks here, I'm lazy
if (this.visited && item.visited && this.contents.equals(item.contents){
this.visited = false; //Unset
item.visited = false;
return true;
}
if (this.visited && !item.visited){
this.visited = false;
return false;
}
if (!this.visited && item.visited){
item.visited = false;
return false;
}
if (!this.visited && !item.visited && this.visited.contents.equals(item.contents){
this.visited = true;
item.visited = true;
boolean ret = this.next.equals(item.next);
this.visited = false;
item.visited = false;
return ret;
}
// Contents not equal
return false;
}
This backtracks and unsets with some basic recursion. I obviously haven't compiled this, but that's the gist of it, I think (I hope there aren't too many errors)
Two issues, first you do not have a circular linked list. The follow code creates 2 lists, list1.next = list2, list2.next = null. No circle created.
LinkedList myList = new LinkedList();
myList.next = new LinkedList();
LinkedList head = myList.next;
myList.next = head;
Second, if you DID have a circular linked list, the following would produce an infinite loop since there is no end condition reached this is because in a circular linked linked, next should never be null.
public boolean equals(Object item) {
return (this == item) || ((item instanceof LinkedList) &&
this.equals((LinkedList)item));
}
public boolean equals(LinkedList item) {
return myUtil.equals(this.contents, item.contents) && myUtil.equals(this.next, item.next);
}
To do this effectively you need to provide SOME mechanism to iterate the list in a non-circular fashion even if this mechanism is private and not exposed to other users. One way to do this would be to mark a single node as the "root".
return myUtil.equals(this.contents, item.contents)
&& myUtil.equals(this.next, item.next);
I would imagine that this is your issue as you suspected, when you perform the second expression of the && namely myUtil.equals(this.next, item.next); you enter the myUtil.equals method which performs this line:
return (x == y) || (x != null && x.equals(y));
Which in turn uses x's .equals() method, which will repeat the process for its item.next, and so on and so forth since you have a circularly linked list.
This will cause an infinite loop, this is because in the code:
public static boolean equals(Object x, Object y) {
return (x == y) || (x != null && x.equals(y));
}
The x.equals(y) will again invoke:
public boolean equals(LinkedList item) {
return myUtil.equals(this.contents, item.contents)
&& myUtil.equals(this.next, item.next);
}
But if you are performing myList1.equals(myList1), you will not get an infinite loop because the (x==y) in myUtils.equals() will return true so infinite loop will not happen if you compare same objects.
However when you compare different objects, you will enter into an infinite loop.
This is not a circular list issue, this is because of the code design you've chosen.
Finally completed my equals method implementation. For this I had to use additional checking tools by myself. I can't tell it is effective, but some extraordinary states are checked.
public boolean equals(Object o)
{
if(!(o instanceof CircularlyLinkedList))
return false;
CircularlyLinkedList<E> list=(CircularlyLinkedList<E>)o;
if(this==list)
return true;
if(size()!=list.size())
return false;
//tail element of this object
Node<E> thisTail=tail;
//tail element of list passing as parameter
Node<E> listTail=list.tail;
//checking if tail elements of both lists are the same or not. If not rotate list till equatation is provided for tails
if(!thisTail.equals(listTail))
{
listTail = equate(list);
if(listTail==null)
return false;
}
//Each element checking
for(int i=0; i<size(); i++)
{
thisTail=thisTail.next;
listTail=listTail.next;
if(!thisTail.equals(listTail))
{
listTail = equate(list);
listTail=tail;
i=0;
if(listTail==null)
return false;
}
}
return true;
}
And equate method:
private Node<E> equate(CircularlyLinkedList<E> list)
{
Node<E> thisTail=tail;
Node<E> listTail;
for(int i=0; i<list.size(); i++)
{
list.rotate();
listTail=list.tail;
//If full rotation completes then returns null
if(list.getRotation()==0)
{
return null;
}
if(thisTail.equals(listTail))
{
return nodeList;
}
}
return null;
}
getRotation method returns count of rotation operation and changes between 0 and size-1. I hope that it will become useful.
I´m trying to find similar rows in multiple two-dimensional arrays as it was described in my previous post. For the below-given example, the answer is false, true, although it should be false, false.
Another very important question is how to adjust this code to arrays with the different number of rows.
I appreciate very much any help. Thanks.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
ArrayList<Integer[]> array1 = new ArrayList<Integer[]>();
ArrayList<Integer[]> array2 = new ArrayList<Integer[]>();
ArrayList<Integer[]> array3 = new ArrayList<Integer[]>();
array1.add(new Integer[]{1,2,3}); array1.add(new Integer[]{1,0,3});
array2.add(new Integer[]{1,0,3}); array2.add(new Integer[]{0,0,3});
array3.add(new Integer[]{1,2,3}); array3.add(new Integer[]{0,3,3});
for (int i=0; i<array1.size(); i++) {
boolean answ = equalRows(array1.get(i),array2.get(i),array3.get(i));
System.out.println(answ);
}
}
static class Row extends Object {
private int value;
public Row(int val) {
this.value = val;
}
#Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if((obj == null) || (obj.getClass() != this.getClass()))
return false;
// object must be Row at this point
Row row = (Row)obj;
return (value == row.value);
}
#Override
public int hashCode () {
return this.value;
}
}
private static Map<Row, Integer> map(Integer[] row) {
Map<Row, Integer> rowMap = new HashMap<Row, Integer>();
for (int i=0; i<row.length; i++)
rowMap.put(new Row(row[i]), i);
return rowMap;
}
private static boolean equalRows(Integer[] row1, Integer[] row2, Integer[] row3){
Map<Row, Integer> map1 = map(row1);
Map<Row, Integer> map2 = map(row2);
for (int i=0; i<row3.length; i++){
Row row = new Row(row3[i]);
Integer result1 = map1.get(row);
Integer result2 = map2.get(row);
if (result1 == null || result2 == null) {
return false;
}
}
return true;
}
}
Edit#1
In the first test I´m comparing {1,2,3}, {1,0,3} and {1,2,3}. In the second: {1,0,3}, {0,0,3}, {0,3,3}. The problem with the second row is that {0,0,3} and {0,3,3} are tackled as {0,3}. I don´t know how to modify the code to deferentiate between {0,0,3} and {0,3,3} (I still should use HashMap).
Edit#2
The idea is that first I take rows from array1 and array2 and I put them into maps. Then I take a row from array3 and try to find it in maps. If I can´t find it in any of these maps, then it means that rows are not similar.
To compare two arrays, ignoring nulls you can have
public static <T> boolean equalsExceptForNulls(T[] ts1, T[] ts2) {
if (ts1.length != ts2.length) return false;
for(int i = 0; i < ts1.length; i++) {
T t1 = ts1[i], t2 = ts2[i];
if (t1 != null && t2 != null && !t1.equals(t2))
return false;
}
return true;
}
public static <T> boolean equalsExceptForNulls3(T[] ts1, T[] ts2, T[] ts3) {
return equalsExceptForNulls(ts1, ts2) &&
equalsExceptForNulls(ts1, ts3) &&
equalsExceptForNulls(ts2, ts3);
}
// or generically
public static <T> boolean equalsExceptForNulls(T[]... tss) {
for(int i = 0; i < tss.length - 1; i++)
for(int j = i + 1; i < tss.length; j++)
if(!equalsExceptForNulls(tss[i], tss[j])
return false;
return true;
}
The problem you have is that array3 is being used to determine which rows to compare.
In the first test you are comparing rows 1,2,3 and the second test you are comparing rows 0 and 3. The first test should be false and the second should be true.
I found the issue by stepping through your code in a debugger. I suggest you do the same.
I would also use int[] instead of Integer[]
I'm not quite sure what you are trying to accomplish but could it be that your problem lies in the method
public boolean equals(Object obj) {
if(this == obj)
return true;
if((obj == null) || (obj.getClass() != this.getClass()))
return false;
// object must be Row at this point
Row row = (Row)obj;
return (value == row.value);
}
because with
if(this == obj)
for example you want to have an value comparison - But what you get using the "==" comperator is a comparison of two objects references ?
So maybe
if(this.equals(obj))
is what you want ?
Furthermore, have you tried to step through your code in debugging mode statement per statement ? I guess doiing so could locate your fault quickly ...
cheers :)
There is a basic problem with your approach which leads to this bug. You are using a map to determine the position of an element in the other rows. When constructing the map if there are duplicate elements in the rows, their previous indices will be overwitten. This is exactly what is happening in your case. There is a duplcate zero in the second row of second array.
here is what the maps look like for the second row
map1 = ((Row(1), 0), (Row(0), 1), (Row(3), 3))
map2 = ((Row(0), 1), (Row(3), 3))
Nnotice there are only two elements in map2 bcoz the first one was overwitten with the second one. When you do a lookup with the elements of the second row from the third array the lookup always succeeds (because it it looks only for a 0 and a 3 and never for a 1)
Moreover the condition you check for failure is incomplete i.e
if (result1 == null || result2 == null) {
return false;
}
should be
if (result1 == null || result2 == null || !result1.equals(i) || !result2.equals(i)) {
return false;
}
In my opinion you shouldn't be using a map at all. Instead compare each element one by one. To generalize the code for arrays of different lengths try using size() method of the ArrayList class.
If is important to you that a map should be used, then you should use the index of each array element as the key and the Row object as the value instead of doing the reverse.