Finding object with smallest member variable - java

Ok so I want to find an algorythm that searches through some objects (in my case 4) and finds the object with the smallest member variable. Lets say you can get that value with object.getIntegerValue()
In my case I have 4 android layouts and want to find the layout with the smallest amount of childs.
I think there will be plenty of solutions but I just want to find a fast one. No matter how dirty and so on....
My Code so far is short, dirty and doesnt always return the object with the smallest member variable, but only has to serve as an Code Example here:
private LinearLayout layoutChanger(){
int one, two, three;
one = layoutOne.getChildCount();
if ((two = layoutTwo.getChildCount()) <= one) {
if ((three = layoutThree.getChildCount()) <= two) {
if ((layoutFour.getChildCount()) <= three)
return layoutFour;
return layoutThree;
}
return layoutTwo;
}
return layoutOne;
}
Edit:
I know how to do this I rather wanted to get suggestions on how to speed up things...
Is Comparable really a fast one? Or should I distinct myself of OOP solutions to get better performance?

Just an example:
int childCount;
Layout[] myLayouts = {layoutOne,layoutTwo,layoutThree};
Layout selected;
for(Layout layout:myLayouts){
if(childCount=0 || childCound>layout.getChildCount()) {
selected = layout;
childCount = layout.getChildCount();
}
}
return layout;

The following is not Java code, this is just (Java like) pseudo code to give the OP an idea...
lowestPossibleValue = ?;
currentLowestValue = MAX;
foreach (object : collection) {
if (object.getValue == lowestPossibleValue) {
foundObject = object;
break;
} else {
if (object.getValue < currentLowestValue) {
foundObject = object;
}
}
}
// foundObject contains your result

private LinearLayout layoutToggler(LinearLayout[] layoutArr){
int currentChildCount;
int minChildCount = MAX_VAL;
LinearLayout retLayout = null;
for(LinearLayout layout:layoutArr){
if((currentChildCount = layout.getChildCount()) == MIN_VAL ){
retLayout = layout;
break;
}
else if(currentChildCount < minChildCount) {
retLayout = layout;
minChildCount = currentChildCount;
}
}
return retLayout;
}
With thanks to Arlington since it is his idea brought to a working solution.

Related

Comparison method violates its general contract in Java [duplicate]

I know this has been an issue for a while now, and checked all previously answers I could get, but still this one doesn't work.
The object 'crew' represents crewmembers with ranks and other items. The comparison should be made by comparing 'assigned_rank', an int value, and if this value is equal in both instances, then 'is_trainer', a boolean, should make the difference.
This method worked great as long as it was running with java < 7. But since Java 7 I keep getting this one:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:714)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:451)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:376)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:182)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at java.util.Collections.sort(Collections.java:155)
at dormas_flightlog.Query.getCrew(Query.java:714)
Here is the source, where some potentially dangerous parts have allready been out-commented, but it still does not work:
public class crew implements Serializable, Comparable<crew> {
private static final long serialVersionUID = 36L;
private int flightID = 0;
private int assigned_rank = 25;
private boolean is_trainer = false;
...
#Override
public int compareTo(crew him) {
int myRank = this.getAssigned_rank();
int hisRank = him.assigned_rank;
if (this == him) {
return 0;
}
if (myRank > hisRank) {
return 1;
}
if (myRank < hisRank) {
return -1;
}
if (myRank == hisRank) {
// if (is_trainer && !o.is_trainer) {
// i = 1;
// }
// if (!is_trainer && o.is_trainer) {
// i = -1;
// }
// if (is_trainer && o.is_trainer) {
// i = 0;
// }
// if (!is_trainer && !o.is_trainer) {
// i = 0;
// }
return 0;
}
return 0;
}
#Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + this.assigned_rank;
hash = 31 * hash + (this.is_trainer ? 1 : 0);
return hash;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
int myRank = this.getAssigned_rank();
int hisRank = 0;
if (o instanceof crew) {
crew him = (crew) o;
hisRank = him.assigned_rank;
} else {
return false;
}
if (myRank > hisRank) {
return false;
}
if (myRank < hisRank) {
return false;
}
if (myRank == hisRank) {
// if (is_trainer && !o.is_trainer) {
// i = 1;
// }
// if (!is_trainer && o.is_trainer) {
// i = -1;
// }
// if (is_trainer && o.is_trainer) {
// i = 0;
// }
// if (!is_trainer && !o.is_trainer) {
// i = 0;
// }
return true;
}
return false;
}
}
Implementing equals() was just a try to solve this problem. The given exception comes with or without equals(). I cannot see how the compareTo-method violates its contract. Any help is greatly appreciated....one day this code has to work with java 7 and I don't know how...
Thanks
see this:
From http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source
Area: API: Utilities Synopsis: Updated sort behavior for Arrays and
Collections may throw an IllegalArgumentException
Description: The sorting algorithm used by java.util.Arrays.sort and
(indirectly) by java.util.Collections.sort has been replaced. The new
sort implementation may throw an IllegalArgumentException if it detects
a Comparable that violates the Comparable contract. The previous
implementation silently ignored such a situation. If the previous
behavior is desired, you can use the new system
property java.util.Arrays.useLegacyMergeSort, to restore previous
mergesort behavior.
Nature of Incompatibility: behavioral
RFE: 6804124
For more detailed info, see the bug database reference here.
maybe you just have NaN values which you compare through Collections.sort(...), this has been a problem to me and I got that exception even having right implementation of compare(obj1, obj2) method! Check that!
I was able to solve this error cause it was a bug in jdk7.
here I found the solution:
"Comparison method violates its general contract!" - TimSort and GridLayout
Basically i just had to add the
JAVA_OPTS="$JAVA_OPTS -Djava.util.Arrays.useLegacyMergeSort=true"
to my jboss
Unfortunately, none of the solutions work for Android. TimSort is used deep in Android's ViewGroup relating to addChildrenForAccessibility that shows up under Java 7 & 8. No user code is involved in any comparison.
From other reports, it is related to having RelativeLayout with overlapping items as is commonly done. For example, a TextView that appears over an Image, or two items at the same location, where you only set one visible at a time.
https://code.google.com/p/android/issues/detail?id=55933
I've not found any way around the bug. You can't set a -Djava option in Android Studio or Eclipse (at least that I could find). Forcing use of Java 1.6 should work, but doesn't. Seems like Amazon's newer Fire tablets and phones are far more sensitive to this bug than other devices.
There are rumors Java 9 will have a fix such as a run-time option that works, but with a bug that's been around for years, I have doubts it will ever be fixed - especially considering the animosity between Oracle and Google. Any yes, perhaps the bug is really deep in the Android code and should be fixed there. With more than a billion devices out there, that's not a viable solution for all the existing devices.

Is there a better way of writing this loop?

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.

Error handling for a while loop

I need help with this scenario where I need to find a string from a pagination table wherein each page contains 50 items. My code below works fine, only problem is that when it cannot find the data my while loop sometimes keep running indefinitely and does not fail but sometimes it does! What can I do so that it will always return an error after reaching a number of loops?
public int inboxLocateLoan(String expName, String name) throws Throwable {
//Locate Loan element in SharePoint table
report.setFailedResult("Loan element is not found");
int loanRow;
try {
boolean loansearch = true;
while (loansearch) {
List < WebElement > rowElem = getWebElements(getAEDriver(), "xpath", sRow);
for (int i = 1; i <= rowElem.size(); i++) {
String actualLoanName = driver.findElement(By.xpath("//*[#id='onetidDoclibViewTbl0']/tbody[2]/tr[" + i + "]/td[3]")).getText();
// String actualLoanNumber = driver.findElement(By.xpath("//*[#id='onetidDoclibViewTbl0']/tbody[2]/tr["+i+"]/td[5]")).getText();
loanRow = i;
if (actualLoanName.equals(expName)) {
loansearch = false;
return loanRow;
}
if (actualLoanName.equals(name)) {
click(getAEDriver(), "xpath", "//*[#class='ms-pivotControl-surfacedOpt-selected']", "Refresh");
loansearch = true;
} else {
if (i == 50) {
click(getAEDriver(), "xpath", "//*[#id='pagingWPQ2next']/a", "Next Page");
} else {
loansearch = true;
}
}
}
}
}
Initialize the romElem outside the for, and then use it to toggle your flag. If you reached your max rowElemen and you didn't find what you were looking for, it is safe then to assume that the value will be false.
Also, what is the purpose of the while? you could remove it completely, it is usually a bad idea to mix a while and a for. I donĀ“t see the point in doing so in this case.

A* algorithm not working properly

I need some help with my A* algorithm implementation.
When I run the algorithm it does find the goal, but the path is definately not the shortest :-P
Here is my code, please help me spot the bugs!
I think it might be the reconstruct path that is my problem but I'm not sure.
public class Pathfinder {
public List<Node> aStar(Node start, Node goal, WeightedGraph graph) {
Node x, y;
int tentative_g_score;
boolean tentative_is_better;
FScoreComparator comparator = new FScoreComparator();
List<Node> closedset = new ArrayList<Node>();
Queue<Node> openset = new PriorityQueue<Node>(10, comparator);
openset.add(start);
start.g_score = 0;
start.h_score = heuristic_cost_estimate(start, goal);
start.f_score = start.h_score;
while (!openset.isEmpty()) {
x = openset.peek();
if (x == goal) {
return reconstruct_path(goal);
}
x = openset.remove();
closedset.add(x);
for (Edge e : graph.adj(x)) {
if (e.v == x) {
y = e.w;
} else {
y = e.v;
}
if (closedset.contains(y) || y.illegal) {
continue;
}
tentative_g_score = x.g_score + e.weight;
if (!openset.contains(y)) {
openset.add(y);
tentative_is_better = true;
} else if (tentative_g_score < y.g_score) {
tentative_is_better = true;
} else {
tentative_is_better = false;
}
if (tentative_is_better) {
y.g_score = tentative_g_score;
y.h_score = heuristic_cost_estimate(y, goal);
y.f_score = y.g_score + y.h_score;
y.parent = x;
}
}
}
return null;
}
private int heuristic_cost_estimate(Node start, Node goal) {
return Math.abs(start.x - goal.x) + Math.abs(start.y - goal.y);
}
private List<Node> reconstruct_path(Node current_node) {
List<Node> result = new ArrayList<Node>();
while (current_node != null) {
result.add(current_node);
current_node = current_node.parent;
}
return result;
}
private class FScoreComparator implements Comparator<Node> {
public int compare(Node n1, Node n2) {
if (n1.f_score < n2.f_score) {
return 1;
} else if (n1.f_score > n2.f_score) {
return -1;
} else {
return 0;
}
}
}
}
Thanks to everyone for all the great answers!
My A* algorithm now works perfectly thanks to you guys! :-)
This was my first post and this forum is really amazing!
You are changing the priority of an element in the PriorityQueue after having inserted it. This isn't supported, as the priority queue isn't aware that an object has changed. What you can do is remove and re-add the object when it changes.
The priority is changed in the line: y.f_score = y.g_score + y.h_score;. This line happens after adding y to the priority queue. Note that simply moving the line openset.add(y); to after calculating the cost won't be enough, since y may have been added in a previous iteration.
It also isn't clear from your code whether the heuristic you used is admissible. If it isn't it will also cause you to get suboptimal paths.
Finally, a performance note: The contains method on ArrayList and PriorityQueue takes linear time to run, which will make the running time of your implememtation non-optimal. You can improve this by adding boolean properties to the nodes to indicate if they are in the closed/open sets, or by using a set data structure.
Priority queue does not update position of item when you change its priority.
Therefore heap property does not hold.
Changed priority affect additions/removals of other items, but it does not repair heap property.
therefore you does not get best item from open -> you don't find shortest path.
You can:
1) write your own heap and maintain index into it
2) add another object into PQ and mark the old one as invalid (you must instead of node put some object with validity flag and referencing node into queue).
2) have worse performance and I advise against it, but some navigation software use this approach (or at least few years back it used).
edit: Best practice is, insert immutable (or at least with imutable parts that means priority) objects into PriorityQueue

Ways to check if an ArrayList contains only null values

I was looking through the code for an old Android application of mine, and I saw one thing I did to the effect of this:
boolean emptyArray = true;
for (int i = 0; i < array.size(); i++)
{
if (array.get(i) != null)
{
emptyArray = false;
break;
}
}
if (emptyArray == true)
{
return true;
}
return false;
There has to be a more efficient way of doing this -- but what is it?
emptyArray is defined as an ArrayList of Integers, which are inserted with a random number of null values (And later in the code, actual integer values).
Thanks!
Well, you could use a lot less code for starters:
public boolean isAllNulls(Iterable<?> array) {
for (Object element : array)
if (element != null) return false;
return true;
}
With this code, you can pass in a much wider variety of collections too.
Java 8 update:
public static boolean isAllNulls(Iterable<?> array) {
return StreamSupport.stream(array.spliterator(), true).allMatch(o -> o == null);
}
There is no more efficient way.
The only thing is you can do, is write it in more elegant way:
List<Something> l;
boolean nonNullElemExist= false;
for (Something s: l) {
if (s != null) {
nonNullElemExist = true;
break;
}
}
// use of nonNullElemExist;
Actually, it is possible that this is more efficient, since it uses Iterator and the Hotspot compiler has more info to optimize instead using size() and get().
It's not detection of contains only null values but it maybe be enough to use just contains(null) method on your list.
Simply Check it worked for me. Hope will work fine for you too!
if (arrayListSubQues!=null){
return true;}
else {
return false }
I use to do something like this :
// Simple loop to remove all 'null' from the list or a copy of the list
while array.remove(null) {
array.remove(null);
}
if (CollectionUtils.isEmpty(array)) {
// the list contained only nulls
}

Categories

Resources