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.
Related
I need to test a dynamic Web Element using Selenium that will change its value after some time(back-end dependent). So, I built a boolean method that returns true if the web element has the value I need and false if that value is never retrieved. I want to check for value change at some intervals (thus, the Thread.sleep between page refreshes). My code always returns true, what am I doing wrong?
public boolean checkStatus() throws InterruptedException {
for(int i=0; i<2;) {
if (!serviceStatus.serviceElement().equals("LIVE")) {
Thread.sleep(5000);
theBrowser.navigate().refresh();
i++;
}else{
return true;
}
}
return false;
}
The method is used in the main test on the following assert:
Ensure.that(checkStatus()).isTrue();
I presume serviceElement() is the Webelement,you have to get the text for the element using getText() method and compare with the string you desire("LIVE") in this scenario.You seems to be comparing an Webelement with String here. Below should work if i understood the requirement correctly.
public boolean checkStatus() throws InterruptedException {
boolean isMatching = false;
for(int i=0; i<2;) {
if (!serviceStatus.serviceElement().getText().equals("LIVE")) {
Thread.sleep(5000);
theBrowser.navigate().refresh();
i++;
isMatching = false;
break;
}else{
isMatching = true;
}
}
return isMatching;
}
I have a small java class that will be run on a cloud application server, so it needs to execute as fast as possible.
What I need to do is iterate over a List<Map>, get the contents of the current Map and then do some logic on it. The Map contains strings and doubles.
This is my current implementation:
for (int i = 0; i < count; i++) {
Map data = result.get(i);
double priceToCheck = Double.parseDouble(data.get("value").toString());
String criteria = data.get("criteria").toString();
String coin = data.get("coin").toString();
if (coin.equals("BTC")) {
if (criteria.equals("above")) {
if (BTC > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (BTC < priceToCheck) {
// create notification
sendNotification = true;
}
}
} else if (coin.equals("BCH")) {
if (criteria.equals("above")) {
if (BCH > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (BCH < priceToCheck) {
// create notification
sendNotification = true;
}
}
} else if (coin.equals("ETH")) {
if (criteria.equals("above")) {
if (ETH > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (ETH < priceToCheck) {
// create notification
sendNotification = true;
}
}
} else if (coin.equals("ETC")) {
if (criteria.equals("above")) {
if (ETC > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (ETC < priceToCheck) {
// create notification
sendNotification = true;
}
}
} else if (coin.equals("LTC")) {
if (criteria.equals("above")) {
if (LTC > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (LTC < priceToCheck) {
// create notification
sendNotification = true;
}
}
} else if (coin.equals("XRP")) {
if (criteria.equals("above")) {
if (XRP > priceToCheck) {
// create notficaition
sendNotification = true;
}
} else {
if (XRP < priceToCheck) {
// create notification
sendNotification = true;
}
}
}
Where result is a List<Map>, "BTC" is a string and BTC is a double
As you can see the highest level if statements checks the string coin, there are six possible values. Once the coin is found I determine the value of criteria, and then do a comparison of doubles depending on the value of criteria
I feel as though this is a very cumbersome way of accomplishing this task, it works but its relatively slow. I can't think of a way to speed it up without directly accessing every Map element and manually checking the contents.
Does anyone else have any ideas?
I have a small java class that will be run on a cloud application server, so it needs to execute as fast as possible.
First of all, there there are some assumptions in there that is doubtful.
Yes, it is nice for your code to run as fast as possible, but in most cases it is not necessary. And in particular, the fact that you running on a cloud server does not necessarily make it essential.
You assume your application is not running fast enough. (Have you benchmarked it?)
You assume that this part of the code is (or will be) responsible for the code being too slow. (Have you implemented it? Have you profiled it?)
And this:
I feel as though this is a very cumbersome way of accomplishing this task, it works but its relatively slow.
Cumbersome and slow are not the same. Often cumbersome verbose / clunky is faster than concise / elegant.
So now to the potential performance issues with your code. (Bearing in mind that this could all be irrelevant of your assumptions are incorrect!)
If the fields are / can be known at compile time, is better to use a custom class than a Map. The Map::get method will be orders of magnitude slower than a getter on a custom class, and a Map will typically use an order of magnitude more memory.
A custom class will also allow you to use primitive types, etcetera instead of shoehorning the values into String. Avoiding that will have performance benefits too.
This is slow:
double priceToCheck = Double.parseDouble(data.get("value").toString());
You appear to be taking a double (or a Double), converting it to a string and then converting it back to adouble`. Conversions between numbers and decimal strings are relatively expensive.
If the values of coin and criteria are known at compile time, consider using an enum or boolean rather than a String. Comparison will be faster, and you will be able to use a switch statement ... or a simple if in the boolean case.
In fact, the iteration through the list is one aspect where this not a lot of opportunity to optimize.
There is one optimization that really stands out here. Your original code snippit will iterate through your entire list to adjust your sendNotification boolean.
If setting sendNotification all you need to do, you can strategically place break in each of your conditional. This will short-circuit the loop after the desired behavior. In the worst case scenario you would end up iterating through your entire list.
for (int i = 0; i < count; i++) {
if (coin.equals("BTC")) {
if (criteria.equals("above")) {
if (BTC > priceToCheck) {
// create notficaition
sendNotification = true;
break; // exits the loop
}
} else {
if (BTC < priceToCheck) {
// create notification
sendNotification = true;
break;
}
}
} else if (coin.equals("BCH")) {
if (criteria.equals("above")) {
if (BCH > priceToCheck) {
// create notficaition
sendNotification = true;
break;
}
how to add if my data first time exist, value will put 1, if the data already exist into hashmap, need put 2 and so on.
below is my coding:
public ArrayList<String> processJson(JSONObject json) {
HashMap<String, Integer> hm = new HashMap<String, Integer>();
ArrayList<String> output = new ArrayList<>();
for (int i = 0; i < hits.length(); i++) {
// to make sure funny/stupid/illogical resp back from ES is caught and ignored!
try {
JSONArray tag = item.getJSONArray("tag");
System.out.println("tag" + hm.entrySet());
if (source.equalsIgnoreCase("trkd")) {
for (int j = 0; j < tag.length(); j++) {
if (j == 0) {
if (!hm.containsKey(tag.toString(0))) {
hm.put(tag.getString(0), 1);
} else {
hm.put(tag.getString(0), new Integer(j + 1));
}
}
}
}
if (hm.containsValue(1)) {
output.add(out);
} else {
output.add(out);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return output;
}
if the value equal to 1, output just add.
but now, my hashmap all is value 1, how to do?
You are doing the compare on
if (!hm.containsKey(tag.toString(0))) {
but updating with
hm.put(tag.getString(j), 1);
so j != 0
I guess the contains should also be using j
Edit
As #Adi points out
Plus, the check the condition 'j==0', this is unnecessary and prevents you from processing beyond first tag.
Instead of a HashMap, you should use a Multimap. Google Guava provides one.
Lots of weird things going on in your code.
Pretty sure tag.toString(int) and tag.getString(int) are not equivalent. I bet you only wanted to use getString
Why is everything happening in j==0 clause? Your loop would effectively only be doing useful stuff only once.
Were you actually trying to code something like this?
if (!hm.containsKey(tag.getString(j))) {
hm.put(tag.getString(j), 1);
} else {
hm.put(tag.getString(j), hm.get(tag.getString(j)+1);
}
The following code doesn't require an if-else since you're doing the same thing in both cases.
if (hm.containsValue(1)) {
output.add(out);
} else {
output.add(out);
}
Can be replaced with:
output.add(out)
I don't think you're explaining very well what you need to do. From whatever I could gather using my code from #3 should get you exactly what you want.
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.
I have a phonegap application and I want to prune the pictures before downloading.
I am passing a JSON object to my function which is
[{"name":"aaa.jpg","link":"https:\/\/www.abc.com\/aaa.jpg"},"name":"bbb.jpg","link":"https:\/\/www.abc.com\/\/bbb.jpg"}]
And using the following function to parse and delete
function prunePictures(pictures) {
for ( var i = 0; i < entries.length; ++i) {
var name = entries[i].name;
$.each(pictures, function(i, obj) {
if (obj.name == name) {
delete pictures[i];
}
});
}
}
But its not going through the loop and I am getting an error "Cannot read property 'name' of undefined"
...you don't want to delete the picture object.
You want to splice it out of the array.
Deleting it leaves a hole in the array, whereas splicing it removes the hole.
var l = entries.length, i = 0, pictureName;
for (; i < l; i += 1) {
pictureName = entries[i].name;
pictures.forEach(function (picture, i, arr) {
if (pictureName === picture.name) { arr.splice(i, 1); }
});
}
Removes the object in pictures if an object in entities has the same name property.
your json string is missing a brace:
[{"name":"aaa.jpg","link":"https:\/\/www.abc.com\/aaa.jpg"},{"name":"bbb.jpg","link":"https:\/\/www.abc.com\/\/bbb.jpg"}]
Edit
I think your json just had a typo, since that's not the error you would get.
You shouldn't delete out of a $.each instead you should use $.grep
see info here
pictures = $.grep(pictures, function(obj,i) {
if (obj.name == name) {
return false;
}
return true;
});