Make function generic for List<Boolean> and boolean[] - java

I have two functions which check if all elements of an array or list are true. I'm having trouble combining the two. How can I make the functions into one generic Java function.
public static boolean allTrue(boolean[] booleans) {
if (booleans == null) {
return false;
}
for (boolean bool : booleans) {
if (!bool) {
return false;
}
}
return true;
}
public static boolean allTrue(List<Boolean> booleans) {
if (booleans == null) {
return false;
}
for (boolean bool : booleans) {
if (!bool) {
return false;
}
}
return true;
}

If you're using Guava, you can wrap the boolean array in Booleans.asList() and pass it as a list:
public static boolean allTrue(boolean[] booleans) {
return booleans != null && allTrue(Booleans.asList(booleans));
}

As per https://stackoverflow.com/a/5606435/2310289
You could just accept an Object
public static boolean allTrue(Object booleans) {
and then check for instanceof boolean[] or instanceof List<Boolean> and then perform different code within the method.
Again, not really an improvement, but a bit closer to code unification

I think the answer given by #Joel was a good one, except for the issue pointed out in the comment. If we just convert boolean[] to Boolean[], we can try the following:
public static boolean allTrue(List<Boolean> booleans) {
if (booleans == null) {
return false;
}
for (boolean bool : booleans) {
if (!bool) {
return false;
}
}
return true;
}
public static boolean allTrue(boolean[] booleans) {
Boolean[] newArray = new Boolean[booleans.length];
int i = 0;
for (boolean value : booleans) {
newArray[i++] = Boolean.valueOf(value);
}
return Arrays.asList(newArray);
}

The common ancestor for List<Boolean> and boolean[] is Object, so unless you are okay with allTrue(Object booleans), you cannot do it with one method.
If you change your method signature to allTrue(Iterable<Boolean> booleans), all you have to do is create a special Iterator<Boolean> to traverse the boolean array.
import java.util.Iterator;
import java.util.NoSuchElementException;
public class BooleanAllTrue {
public static boolean allTrue(Iterable<Boolean> booleans) {
if (booleans == null) return false;
for (Boolean bool : booleans) {
if (!bool) return false;
}
return true;
}
public static Iterable<Boolean> asIterable(final boolean[] booleens) {
return new Iterable<Boolean>() {
public Iterator<Boolean> iterator() {
final boolean[] booleans = booleens;
return new Iterator<Boolean>() {
private int i = 0;
public boolean hasNext() {
return i < booleans.length;
}
public Boolean next() {
if (!hasNext()) throw new NoSuchElementException();
return booleans[i++];
}
public void remove() {throw new UnsupportedOperationException("remove");}
};
}
};
}
public static void main(String [] args) {
System.out.println(allTrue(asIterable(new boolean[]{true, true})));
System.out.println(allTrue(asIterable(new boolean[]{true, false})));
try {
asIterable(new boolean[0]).iterator().next();
} catch (NoSuchElementException e) {
// expected
}
}
}
And finally the allTrue(boolean[] booleans) method.
public static boolean allTrue(boolean[] booleans) {
return allTrue(asIterable(booleans));
}

Related

How to implement equals method which works on generics

I have the following problem. I have the following classes
public class Main {
public static void main(String[] args) {
// Expected: true
// Results in: true
List<String> strLst = new ArrayList<>();
strLst.add(new String("A"));
System.out.println(strLst.contains(new String("A")));
// Expected: true
// Results in: true
List<Number> numLst = new ArrayList<>();
numLst.add(new Number(1));
System.out.println(numLst.contains(new Number(1)));
// Expected: true
// Results in: false
Container<String> integers = new Container<>();
integers.add(new String("A"));
System.out.println(integers.contains(new String("A")));
// Expected: true
// Results in: false
Container<Number> numbers = new Container<>();
numbers.add(new Number(1));
System.out.println(numbers.contains(new Number(1)));
}
}
class Container<T> {
ArrayList<Node<T>> internal = new ArrayList<>();
public void add(T elem) {
internal.add(new Node<>(elem));
}
public boolean contains(T label) {
for (Node<T> e : internal) {
if (e.getLabel().equals(e)) {
return true;
}
}
return false;
}
}
class Node<T> {
T label;
public Node(T label) {
this.label = label;
}
public T getLabel() {
return label;
}
}
class Number {
private int val;
public Number(int val) {
this.val = val;
}
public boolean equals(Object o) {
if (o instanceof Number) {
return this.val == ((Number) o).val;
}
return false;
}
}
I am not sure what went wrong here. I would expect similar behavior with my Container as with ArrayList. But it does not, because in my opinion ArrayList (see https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/ArrayList.java#L251) implements contains in a similar way.
What does ArrayList do different than I do? And if it is not possible to implement such behavior the way I hope to, how would I do this alternatively?
The line
if (e.getLabel().equals(e)) {
in contains should be
if (e.getLabel().equals(label)) {
Solution:
public boolean contains(T label) {
for (Node<T> e : internal) {
if (e.getLabel().equals(label)) {
return true;
}
}
return false;
}

How to make custom Tuple class generic?

I'm trying to make a generic tuple class. It stores its elements as an ArrayList. Of course, this class should override hashcode and equals methods.
How could I make hashcode method for this class? You see, in the code, I am having trouble.
Also, for the equals method, why does the compiler force me to use the '?'. Why couldn't I just use the T?
public static class Tuple<T> {
ArrayList<T> tuple = new ArrayList<>();
public Tuple(ArrayList<T> items) {
for (T item : items) {
tuple.add(item);
}
}
#Override
public int hashCode() {
T sum = ???;
for (T item : tuple) {
sum += item.hashCode();
}
return sum;
}
#Override
public boolean equals(Object o) {
if (o instanceof Tuple<?>) {
Tuple<?> tup= (Tuple<?>) o;
if (tup.tuple.size() != this.tuple.size()) {
return false;
}
for (int i = 0; i < this.tuple.size(); i++) {
if (this.tuple.get(i) != tup.tuple.get(i)) {
return false;
}
}
return true;
} else {
return false;
}
}
}
As mentioned in the comments, we should delegate the hashCode and the equals methods to the ArrayList<T> tuple instance variable. For the hashCode it's trivial. For the equals it's just a little more complicated than that because we don't want our custom Tuple to be equals with an ArrayList. So here it is:
public class Tuple<T> {
// I made this private because I'm pedantric ;)
private final ArrayList<T> tuple = new ArrayList<>();
// this does the same as your code, it's just easier to read
public Tuple(ArrayList<T> items) {
tuple.addAll(items);
}
#Override
public int hashCode() {
return tuple.hashCode();
}
// generated by eclipse
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Tuple other = (Tuple) obj;
if (tuple == null) {
if (other.tuple != null)
return false;
} else if (!tuple.equals(other.tuple))
return false;
return true;
}
}
If you want to deal with the case when the tuple can be null, then you can use a slightly more complex hashCode:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((tuple == null) ? 0 : tuple.hashCode());
return tuple.hashCode();
}
In general, I don't like to write these methods myself. Usually, I make my IDE to generate the stuff. All I need to take care of is to re-generate it when I add new fields. Apache HashCodeBuilder and EqualsBuilder are also great alternatives.

How would I run this method with the main method?

This is is the code:
public class monkeyTrouble {
public static void main(String[]args){
monkeyTrouble s = new monkeyTrouble();
s.trouble(false, false);
}
public boolean trouble (boolean aSmile, boolean bSmile) {
if (aSmile == true && bSmile == true){
return true;
} else if (aSmile == false && bSmile == false) {
return true;
} else {
return false;
}
}
}
How can I run the boolean method in the main method so it will correctly run?
First, you are already running your method; you aren't displaying or storing the result. You could print the result like
public static void main(String[]args){
monkeyTrouble s = new monkeyTrouble();
System.out.println(s.trouble(false, false));
}
Also, your method could be simplified like
public boolean trouble (boolean aSmile, boolean bSmile) {
return aSmile == bSmile;
}

returning true with an occurance of a letter in a string?

it should return true as there is 'c' in the string S but it keeps returning False?
public class A {
public static void main(String[] args){
System.out.println(contains('c', "cccc"));
}
public static boolean contains(char c, String s) {
boolean to_return = true;
while(true) {
if(s.equals("")){
return to_return = false;
} else {
char c2 = s.charAt(0);
if(c==c2) {
to_return = true;
}
}
s=s.substring(1);
}
}
}
I have NO idea why it isnt? it only returns false if the string is empty which is clearly is(I am NOT allowed to use for loops etc..
you are not returning true anywhere in your code. So recursion happens till s.equals("") is evaluated to true and returns false.
Change
if(c==c2) {
to_return = true;
}
to
if(c==c2) {
return true;
}
works:
public static boolean contains(char c, String s) {
return s.indexOf(c) != -1;
}
If you want a loopy version, use a for loop like this, as it should be cleaner:
public static boolean contains(char c, String s) {
boolean to_return = true;
for(int i=0;i<s.length();i++) {
if(s.charAt(i) != c) {
to_return = false;
}
}
return to_return;
}
Alternatively, you can just do:
public static boolean contains2(char c, String s) {
return s.contains(String.valueOf(c));
}
Can you try a more cleaner method, it seems too cluttered.
public static boolean contains(char c, String s) {
if (s == null)
return false;
if (s.equals(""))
return false;
int size = s.length();
for (int i = 0; i < size; i ++) {
if(s.charAt(i) == c)
return true;
}
return false;
}

Problems with add/remove/equals/string-method in MultiSet-class

This is my class:
public class MultiSet<E> extends AbstractCollection<E>
{
private int size = 0;
private Map<E, Integer> values = new HashMap<E, Integer>();
public MultiSet()
{
}
public MultiSet(Collection<E> c)
{
addAll(c);
}
#Override
public boolean add(E o)
{
throw new UnsupportedOperationException();
}
#Override
public boolean remove(Object o)
{
throw new UnsupportedOperationException();
}
public Iterator<E> iterator()
{
return new Iterator<E>()
{
private Iterator<E> iterator = values.keySet().iterator();
private int remaining = 0;
private E current = null;
public boolean hasNext()
{
return remaining > 0 || iterator.hasNext();
}
public E next()
{
if (remaining == 0)
{
remaining = values.get(current);
}
remaining--;
return current;
}
public void remove()
{
throw new UnsupportedOperationException();
}
};
}
public boolean equals(Object object)
{
if (this == object) return true;
if (this == null) return false;
if (this.getClass() != object.getClass()) return false;
MultiSet<E> o = (MultiSet<E>) object;
return o.values.equals(values);
}
public int hashCode()
{
return values.hashCode()*163 + new Integer(size).hashCode()*389;
}
public String toString()
{
String res = "";
for (E e : values.keySet());
//res = ???;
return getClass().getName() + res;
}
public int size()
{
return size;
}
}
So basically, i need to implement my add/remove-methods correctly, to add or remove elements to/from the Set.
To me, it seems like my equals is correct, but Eclipse says that in the line:
MultiSet<E> o = (MultiSet<E>) object;
there is an unchecked cast from object to Multiset<E>
Any thoughts?
Also, in my toString method, i'm not 100% sure how to define "res"?
Thanks,
// Chris
use this instead:
MultiSet<?> o = (MultiSet<?>) object;
this is necessary due to how generics are implemented in java.

Categories