Is there a better way of writing this loop? - java

I need to check whether at least 1 item in a list has X, Y, and Z (not all at the same time). e.g. item 1 has x, and item 2 has y and z.
I thought it'd be better to do this without creating multiple loops and just checking for one of them, but instead store a variable and then check it so it can't be set to false again once true.
Seems like I'm probably missing a better way to do this, so is there one?
Thanks
boolean hasX = false;
boolean hasY = false;
boolean hasZ = false;
for (ItemType item : Items) {
if (!hasX) { hasX = DoesHaveX(item); }
if (!hasY) { hasY = DoesHaveY(item); }
if (!hasZ) { hasZ = DoesHaveZ(item); }
}

If you are going to stick to a JVM below 1.8 then your code is just fine!
Maybe you could skip few operations like breaking the loop once you found a match for the three booleans, and checking only those which are not found any yet.
for (ItemType item : items) {
hasX = hasX || doesHaveX(item);
hasY = hasY || doesHaveY(item);
hasZ = hasZ || doesHaveZ(item);
if (hasX && hasY && hasZ) {
break;
}
}
If you are just fine to use streams maybe it's better to initialize each of the variables at it's creation like so:
boolean hasX = items.stream().anyMatch(this::doesHaveX); // goes trough the elements until a match is found.
boolean hasY = items.stream().anyMatch(this::doesHaveY); // goes trough the elements until a match is found.
boolean hasZ = items.stream().anyMatch(this::doesHaveZ); // goes trough the elements until a match is found.

Here is an extendable approach that uses an enum so you never have to touch the logic of hasOneOfAll again. You just have to extend the given enum.
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
class StackOverflowQuestion56902308Scratch {
class ItemType {
boolean x;
boolean y;
boolean z;
}
enum ItemTypeCheck implements Predicate<ItemType> {
HASX() {
#Override
public boolean test(ItemType itemType) {
//TODO: implement me
return itemType.x;
}
},
HASY() {
#Override
public boolean test(ItemType itemType) {
//TODO: implement me
return itemType.y;
}
},
HASZ() {
#Override
public boolean test(ItemType itemType) {
//TODO: implement me
return itemType.z;
}
}
}
public static boolean hasOneOfAll(List<ItemType> itemTypes) {
Map<ItemTypeCheck, Boolean> result = new EnumMap<>(ItemTypeCheck.class);
for (ItemType itemType : itemTypes) {
for (ItemTypeCheck check : ItemTypeCheck.values()) {
result.merge(check, check.test(itemType), Boolean::logicalOr);
}
}
return result.values().stream().allMatch(hadOne -> hadOne);
}
}
Personally I am not sure if this is too overengineered but it alleviates the pain of manually adjusting the function if another check is added in the future.

A Stream map/reduce version of the loop for fun. Not sure if it is better to be honest. But at least we get rid of all the variables
map each item to a list of 3 booleans (one for each attribute x,y,z)
reduce the whole list into a list of 3 booleans (one for each attribute x,y,z) checking if any of the items has each value
check that all the elements of the the resulting list are true.
boolean allGood = items.stream()
.map(i -> Arrays.asList(doesHaveX(i), doesHaveY(i), doesHaveZ(i)))
.reduce(Arrays.asList(false, false, false),
(acc, elem) -> Arrays.asList(acc.get(0) || elem.get(0),
acc.get(1) || elem.get(1),
acc.get(2) || elem.get(2)))
.stream()
.allMatch(Boolean::booleanValue);

Just to add a BitSet variant too, and under the assumption that checking has... is a semi-expensive operation:
private static final int xBit = 0;
private static final int yBit = 1;
private static final int zBit = 2;
public static boolean hasAll(final Collection<ItemType> items) {
if (items.isEmpty()) return false;
final BitSet bits = new BitSet(3);
for (final ItemType item : items) {
// Check if bit is already set to avoid
// needless `has*` evaluation
if (!bits.get(xBit) && hasX(item)) bits.set(xBit);
if (!bits.get(yBit) && hasY(item)) bits.set(yBit);
if (!bits.get(zBit) && hasZ(item)) bits.set(zBit);
// You could repeat this INSIDE all of the 'if's
// above to potentially avoid computing bits.get
// but I'd sacrifice that for the slightly improved
// readability.
if (bits.cardinality() == 3) return true;
}
return false;
}
I can't tell you if this is faster or anything, as that depends on your has* implementations, amongst other things. But it avoids most recomputations whereever possible.

Related

Preferable way to avoid if(condition) return true

I keep finding methods having code like this:
public boolean checkSomethingForCollection(Collection<Something> things){
for(Something thing:things){
boolean satisfiesCondition = check(thing);
if(satisfiesCondition){
return true;
}
}
return false;
}
private static boolean check(Something something){
//omitted...
}
I am fully aware of the fact that the public method will stop by reaching 'return' if the check(..) returns true, but it still looks ugly to me.
What would be preferable? Using break; instead to have one return only, or refactor to something else? Having
if(booleanExpression){
return true;
}
just makes me sick.
You can't do that with a "java for each", but you can avoid it with a normal for like this :
boolean satisfiesCondition = false;
for (int i = 0; i < size && !satisfiesCondition; ++i) {
satisfiesCondition = check(things[i]);
}
return satisfiesCondition;
Java streams in Java 8 make this pretty easy - the Stream.anyMatch method taking a predicate is exactly what you want. In this case you can use a method reference to create a predicate from the check() method.
public boolean checkSomethingForCollection(Collection<Something> things) {
return things.stream().anyMatch(this::check);
}
Here's a short but complete example:
import java.util.*;
public class Test {
private final int minLength;
private Test(int minLength) {
this.minLength = minLength;
}
public boolean checkAny(Collection<String> things) {
return things.stream().anyMatch(this::check);
}
private boolean check(String x) {
return x.length() >= minLength;
}
public static void main(String[] args) throws Exception {
Test t = new Test(5);
List<String> shortStrings = Arrays.asList("asd", "bcd", "foo");
List<String> mixedStrings = Arrays.asList("asd", "bcd", "this is long", "foo");
System.out.println(t.checkAny(shortStrings)); // false
System.out.println(t.checkAny(mixedStrings)); // true
}
}
I haven't checked the code, but you should be able to do something like this:
things.stream()
.filter(x -> check(x))
.findFirst()
You can find some more information here.
Since the for makes use of an iterator, you could opt to use a while loop instead:
Iterator<Something> iter = things.iterator();
boolean isValid= false;
while(iter.hasNext() && !isValid)
isValid = check(iter.next());
return isValid;
That being said, I think that your current version of things is more readable.

Suspicious call to Collection.contains method in ArrayList

I am getting a warning that watchStore.contains(s) is a suspicious call to java.util.Collection#contains. How can I fix it? I want to use contains() to find a particular object with the matching serial number.
public Watch findWatchBySerialNumber(long srch) {
long s = srch;
Watch watch = null;
for(int i = 0; i < watchStore.size(); i++) {
watch = watchStore.get(i);
if(watchStore.contains(s)) {
System.out.print("item found");
return watch;
}
}
System.out.print("item not found");
return null; // watch is not found.
}
Presuming that Watch is the class, watchStore is a List<Watch>, and that a field serialNo exists on Watch...
public Optional<Watch> findWatchBySerialNumber(long serial) {
return watchStore.stream()
.filter(w -> w.getSerialNo() == serial)
.findFirst();
}
If you're not using Java 8, the code is close, but a bit more dangerous since you have the chance to return null. If you can use Guava's Optional, that'd be a better choice here.
public Watch findWatchBySerialNumber(long serial) {
for(Watch w : watchStore) {
if(w.getSerialNo() == serial) {
return w;
}
}
return null;
}
Your contains isn't going to work since your list doesn't contain Longs, it contains Watchs. This is also why the compiler sees it as dubious; contains accepts an Object but it will return false if what you're looking for doesn't have a comparable equals for what's in your list.
You have to iterate over the entirety of your collection to find it in this scenario, especially since you're looking for a specific property on those objects as opposed to a specific, easy-to-provide value.
please how can I fix that. I want to use the contain() to find a
particular object with the matching serial number.
In that case override Watch's equals() to use serialNumber field for comparison.
Then add constructor that accepts serialNumber.
public class Watch {
private final long serialNumber;
public Watch(long serialNumber) {
this.serialNumber = serialNumber;
}
#Override
public boolean equals(Object obj) {
return obj == this ||
(obj instanceof Watch && ((Watch)obj).serialNumber == serialNumber);
}
#Override
public int hashCode() {
return (int)serialNumber;
}
}
Replace if(watchStore.contains(s)){ with if(watchStore.contains(watchToFind)){ where Watch watchToFind = new Watch(s);
you can use contains method from org.apache.commons.lang.ArrayUtils package.
Checks if the value is in the given array.
The method returns false if a null array is passed in.
Parameters:
array the array to search through
valueToFind the value to find
Returns:
true if the array contains the object
long [] imageHashes= {12l,13l,14l,15l};
System.out.println(ArrayUtils.contains(imageHashes, 13l));

Using wrapper class instead of static variables

This is my first question ever at StackOverFlow:
I am studying to interviews with the help of "Cracking the code interview" (5th Edition) book,
and I was solving the next problem:
Implement a function to check if a binary tree is a binary search tree (Q 4.5 pg 86).
Before we move on, I would like just to remind you the difference between a Binary search tree to a simple Binary tree:
A Binary search tree imposes the condition that for all nodes, the left children are less than or equal to the current node, which is less than all the right nodes.
So one of the solution the book offers is to scan the tree with In-Order traversal and on the fly to check if every node we visit is greater then the last one, and it assumes the tree can't have a duplicate values:
public static int last_printed = Integer.MIN_VALUE;
public static boolean checkBST(TreeNode n) {
if(n == null) return true;
// Check / recurse left
if (!checkBST(n.left)) return false;
// Check current
if (n.data <= last_printed) return false;
last_printed = n.data;
// Check / recurse right
if (!checkBST(n.right)) return false;
return true; // All good!
}
Now, up here everything is good, but then the book quotes :
If you don't like the use of static variables, then you can tweak this code to use a wrapper class for the integer, as shown below:
Class WrapInt {
public int value;
}
After reading on wrapper class all over here and in other websites I just couldn't come to the conclusion, why and how should I use the wrapper class here instead of the static variable?
This is a mechanism whereby you can create an instance of WrapInt, and pass it around. You then expose the value only to code that should know about it, instead of a public static non-final variable that can be accessed and changed from anywhere.
The reason you have the wrapper class is because Java primitives are pass-by-value; passing around an int and then updating it wouldn't propagate the change through the rest of your system.
This would look like this:
public static boolean checkBST(TreeNode n) {
WrapInt counter = new WrapInt();
return checkBST(n, counter);
}
public static boolean checkBST(TreeNode n, WrapInt counter) {
if(n == null) return true;
// Check / recurse left
if (!checkBST(n.left, counter)) return false;
// Check current
if (n.data <= counter.value) return false;
counter.value = n.data;
// Check / recurse right
if (!checkBST(n.right, counter)) return false;
return true; // All good!
}
Here you go:
public static boolean checkBST(TreeNode n) {
WrapInt i = new WrapInt();
i.value = INTEGER.MIN_VALUE;
doCheckBST(n, i);
}
private static boolean doCheckBST(TreeNode n, WrapInt last_printed) {
if(n == null) return true;
// Check / recurse left
if (!checkBST(n.left, last_printed)) return false;
// Check current
if (n.data <= last_printed.value) return false;
last_printed.value = n.data;
// Check / recurse right
if (!checkBST(n.right, last_printed)) return false;
return true; // All good!
}
If there is the possibility that there will run 2+ sorts at the same time. The static will be used for both sortings. Both sortings have access to the same static value.
//thread 1
Sorting A = new Sorting(5,9,8);
A.sort();
//thread 2
Sorting B = new Sorting(999,100,7);
B.sort();
We cant predict which/how the thread is processed.
So this could end up in
A.checkBST(5) // last_printed = 5
B.checkBST(999) // last_printed = ??
B.checkBST(100) // last_printed = ??
A.checkBST(9) // last_printed = ??
...
...
If every sort instance has his own last_printed, you won't have synchronisation issues.
I think this is more formal way how to avoid of public static context property (e.g for thread safety), which is not optimal approach in object programming. But there are standard Primitive wrapper classes as: https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html
which can be used instead of new classes. Generally Wrapper pattern can be more general than your example: What is a wrapper class?
The problem with static variable is that another class/method or something can modify it and it will break your code.
Can you make it like that:
Class WrapInt {
public int value=Integer.MIN_VALUE;
}
public static boolean checkBST(TreeNode n,WrapInt lastPrinted) {
if(n == null) return true;
// Check / recurse left
if (!checkBST(n.left,lastPrinted)) return false;
// Check current
if (n.data <= lastPrinted.value) return false;
lastPrinted.value = n.data;
// Check / recurse right
if (!checkBST(n.right,lastPrinted)) return false;
return true; // All good!
}

Java class that efficiently handle the contains operation

I'm using inside an iterative algorithm an HashSet that is dynamically enlarged at each algorithm iteration by adding new objects (via method add). Very frequently I check if a generated object has been already put inside the HashSet by using the contains method. Observe that the HashSet may include several thousand objects.
Here follows a citation from the doc about class HashSet:
"This class offers constant time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets."
Apart from other considerations provided inside the doc (not reported for simplicity), I see that add and contains are executed in constant time.
Please, can you suggest another data structure in Java that provides better performance for the "contains" operation with respect to my problem?
Classes from Apache Commons or Guava are also accepted.
The performance of HashSet.contains() will be as good as you can get provided your objects have a properly implemented hashCode() method. That will ensure proper distribution among the buckets.
See Best implementation for hashCode method
As other answers already stated "constant time" is the best runtime-behaviout you can get.
If you will get it does depend on your hashcode-implementation, but since you use the NetBeans suggestion you shouldn't be too bad there.
As to how to keep the "constant time" as small as possible:
try to allocate your HashSet large enough from the very beginning to avoid costly rehash-operations
You can cache your calculated hashcode the first time hashCode() is called and return the cached value later on. There should be no need to add some triggering-mechanism to clear the cache on object-updates, since your relevant fields should be immutable - if they aren't you are bound to run into trouble using HashSet anyway.
You can let your object remember if it has been put in that hashset. Just have a boolean field to store if it was added to the hash set. Then you don't need to call contains on the HashSet but just read the field value of your object. This method will only work if the object is put in exactly one hashset that will check the boolean field.
It might be extended to a constant number of hashsets using java.util.BitSet in the object contained in the hashset where every hashset can be identified by a unique integer when the number of hashsets is known before the algorithm starts.
Since you are saying that you are calling contains frequently, it makes sense to replace newly generated objects with equal existing objects (object pooling), since the overhead of that will amortize by having contains being only a single field read.
As requested here is some sample code. The special set implementation is about 4 times faster than a normal hash set on my machine. However the question is how well this code reflects your use case.
public class FastSetContains {
public static class SetContainedAwareObject {
private final int state;
private boolean contained;
public SetContainedAwareObject(int state) {
this.state = state;
}
public void markAsContained() {
contained = true;
}
public boolean isContained() {
return contained;
}
public void markAsRemoved() {
contained = false;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + state;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SetContainedAwareObject other = (SetContainedAwareObject) obj;
if (state != other.state)
return false;
return true;
}
}
public static class FastContainsSet extends
HashSet<SetContainedAwareObject> {
#Override
public boolean contains(Object o) {
SetContainedAwareObject obj = (SetContainedAwareObject) o;
if (obj.isContained()) {
return true;
}
return super.contains(o);
}
#Override
public boolean add(SetContainedAwareObject e) {
boolean add = super.add(e);
e.markAsContained();
return add;
}
#Override
public boolean addAll(Collection<? extends SetContainedAwareObject> c) {
boolean addAll = super.addAll(c);
for (SetContainedAwareObject o : c) {
o.markAsContained();
}
return addAll;
}
#Override
public boolean remove(Object o) {
boolean remove = super.remove(o);
((SetContainedAwareObject) o).markAsRemoved();
return remove;
}
#Override
public boolean removeAll(Collection<?> c) {
boolean removeAll = super.removeAll(c);
for (Object o : c) {
((SetContainedAwareObject) o).markAsRemoved();
}
return removeAll;
}
}
private static final Random random = new Random(1234L);
private static final int additionalObjectsPerIteration = 10;
private static final int iterations = 100000;
private static final int differentObjectCount = 100;
private static final int containsCountPerIteration = 50;
private static long nanosSpentForContains;
public static void main(String[] args) {
Map<SetContainedAwareObject, SetContainedAwareObject> objectPool = new HashMap<>();
// switch comment use different Set implementaiton
//Set<SetContainedAwareObject> set = new FastContainsSet();
Set<SetContainedAwareObject> set = new HashSet<>();
//warm up
for (int i = 0; i < 100; i++) {
addAdditionalObjects(objectPool, set);
callSetContainsForSomeObjects(set);
}
objectPool.clear();
set.clear();
nanosSpentForContains = 0L;
for (int i = 0; i < iterations; i++) {
addAdditionalObjects(objectPool, set);
callSetContainsForSomeObjects(set);
}
System.out.println("nanos spent for contains: " + nanosSpentForContains);
}
private static void callSetContainsForSomeObjects(
Set<SetContainedAwareObject> set) {
int containsCount = set.size() > containsCountPerIteration ? set.size()
: containsCountPerIteration;
int[] indexes = new int[containsCount];
for (int i = 0; i < containsCount; i++) {
indexes[i] = random.nextInt(set.size());
}
Object[] elements = set.toArray();
long start = System.nanoTime();
for (int index : indexes) {
set.contains(elements[index]);
}
long end = System.nanoTime();
nanosSpentForContains += (end - start);
}
private static void addAdditionalObjects(
Map<SetContainedAwareObject, SetContainedAwareObject> objectPool,
Set<SetContainedAwareObject> set) {
for (int i = 0; i < additionalObjectsPerIteration; i++) {
SetContainedAwareObject object = new SetContainedAwareObject(
random.nextInt(differentObjectCount));
SetContainedAwareObject pooled = objectPool.get(object);
if (pooled == null) {
objectPool.put(object, object);
pooled = object;
}
set.add(pooled);
}
}
}
Anothe Edit:
using the following as the Set.contains implementation makes it about 8 times faster than a normal hashset:
#Override
public boolean contains(Object o) {
SetContainedAwareObject obj = (SetContainedAwareObject) o;
return obj.isContained();
}
EDIT:
This technique has a bit with the class enhancement of OpenJPA in common. The enhancement of OpenJPA enables a class to track its persistent state which is used by the entity manager. The suggested method enables an object to track if itself is contained in a set which is used by the algorithm.

contains giving faulty results

I have a class 'CoAutoria' that's suposed to hold 2 instances of an 'Author' class (which only has a name, for now) and the number of articles those authors have in common.
In order to figure out the top 10 of co-authors (regarding number of articles) I created a TreeSet of 'CoAutoria', to hold the total of articles, for each pair.
I need to cycle through a Map of years, gather the different authors and their respective Set of co-Authors. Then, for each pair, create an instance of 'CoAutoria' and: add it to the treeset (if it doesn't already exists); or simply sum its number of articles to the one existing on the set.
I already created the compareTo method, to insert it on the treeset, and created the equals method so that the order of the authors doesn't matter.
Here's the main code:`
public class CoAutoria implements Comparable<CoAutoria>
{
private Autor autor1;
private Autor autor2;
private int artigosComum;
(...)
}
#Override
public int compareTo(CoAutoria a2)
{
String thisAutor1 = autor1.getNome();
String thisAutor2 = autor2.getNome();
String caAutor1 = a2.getAutor1().getNome();
String caAutor2 = a2.getAutor2().getNome();
if((autor1.equals(a2.getAutor1()) && autor2.equals(a2.getAutor2())) || (autor1.equals(a2.getAutor2()) && autor2.equals(a2.getAutor1())))
{
return 0;
}
else
{
return 1;
}
}
#Override
public boolean equals(Object o)
{
if(this == o)
{
return true;
}
if( o == null || o.getClass() != this.getClass())
return false;
CoAutoria ca = (CoAutoria) o;
String thisAutor1 = autor1.getNome();
String thisAutor2 = autor2.getNome();
String caAutor1 = ca.getAutor1().getNome();
String caAutor2 = ca.getAutor2().getNome();
if((thisAutor1.equals(caAutor1) && thisAutor2.equals(caAutor2)) || (thisAutor1.equals(caAutor2) && thisAutor2.equals(caAutor1)))
{
return true;
}
else
{
return false;
}
}
The main problem is: When I check if the set already has a certain instance of 'CoAutoria', (I'm using the contains() method of TreeSet), it gives me faulty results...sometimes it checks correctly that the Pair A-B already exists in that set (on the form of B-A), but sometimes it doesn't... For what I've read, the contains uses the equals method, so that's not suposed to happen..right?
[EDIT:]
Since the first post I started to think that maybe the problem resided on the compareTo..So I changed it to
public int compareTo(CoAutoria a2)
{
String thisAutor1 = autor1.getNome();
String thisAutor2 = autor2.getNome();
String caAutor1 = a2.getAutor1().getNome();
String caAutor2 = a2.getAutor2().getNome();
if(this.equals(a2))
{
System.out.println("return 0");
return 0;
}
else
{
int aux = thisAutor1.compareTo(caAutor1);
if(aux != 0)
{
return aux;
}
else
{
return thisAutor2.compareTo(caAutor2);
}
}
}
But it still gives my bad results..I thought I'd figured it now: if it's the same 'CoAutoria', I return 0, if not I go through the names, and order it by their compareTo values..but something's missing
Your contains method is breaking, because your compareTo method is always returning 0 or positive, no negatives. This means your compareTo is inconsistent. A correct implementation should return 0 if the authors are the same, or positive and negative values when the authors are different.
Example (assuming author1 is different than author2):
int i = author1.compareTo(author2); // i should be positive or negative
int j = author2.compareTo(author1); // j should be the opposite of i
Yours will return 1 for both of the above cases, which will make ordered Collections not work as no element is ever smaller. As another example imagine if you had a Binary Tree(an ordered collection) that had the elements [1-10]. If you were searching for the element 5, your binary tree when comparing 5 against any element would always say that it was equal or greater.
How exactly you should change it is up to you. But an idea would be to sort the authors by name, then iterate over both collections and compare the authors together lexicographically.
EDIT: Even after your edit to your methods they are still not consistent. Try the following, they aren't the most efficient but should work unless you really want to optimize for speed. Notice they first sort to make sure author1 and author2 are in order before they are compared with the other CoAutor which is also sorted. I don't do any null checking and assume both are valid authors.
#Override
public boolean equals(Object o){
if (o == null || !(o instanceof CoAutoria)) return false;
if (o == this) return true;
return this.compareTo((CoAutoria)o) == 0;
}
#Override
public int compareTo(CoAutoria o) {
List<String> authors1 = Arrays.asList(autor1.getNome(), autor2.getNome());
List<String> authors2 = Arrays.asList(o.autor1.getNome(), o.autor2.getNome());
Collections.sort(authors1);
Collections.sort(authors2);
for (int i=0;i<authors1.size();i++){
int compare = authors1.get(i).compareTo(authors2.get(i));
if (compare != 0)
return compare;
}
return 0;
}

Categories

Resources