I have written a code in JESS. I am now running the code from Java. I have run to this problem that I want to have the engine.execute("") command in a for loop.
My example code is :
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
r.executeCommand("(answer(ident headers.get(i)(text patientData.get(j).get(i))");
}
}
where answer is a deftemplate in JESS with two slots. I am reading a text file in Java and inserting the values in the slots of the deftemplate.
Thanks,
Ali
If answer is a deftemplate with slots ident and text, the following snippet looks like the construction of a fact:
(answer(ident headers.get(i)(text patientData.get(j).get(i))
A bare fact does not represent a Jess command that can be executed via Rete.executeCommand.
You shouldn't use the deprecated method executeCommand; use eval.
Your parentheses aren't balanced properly, 6 opening parentheses against 4 closing ones.
Assuming that headers is a List<String> in your Java application, you cannot simply throw a Java method call at Jess, which doesn't understand Java syntax in the first place and (presumably) doesn't know about the pojo header at all.
The same is true for the pojo patientData.
While you might pass objects from your Java program to the Jess engine, this is absolutely impossible for simple variables like i and j.
Considering all of this (most of which is easy to learn from the excellent Jess manual), using
r.eval( "(assert (answer (ident \"" +
headers.get(i) +
"\")(text \"" +
patientData.get(j).get(i) +
"\")))" );
might have a chance of succeeding and indeed insert a new fact into working memory.
Related
If i have the following input:
sometext 23,1 -54.2 42
sometext 42,6 32 -56
How do i read firstly only the string and then the numbers.
for(int i = 0 ; i < numLines ; i++){
name = scanner.nextLine() // Here i want to save "sometext"
for(int j = 0 ; j < numNumbers ; j++){
numbers.add(scanner.nextFloat());
}
cities.add(new City(name, numbers));
numbers.clear();
}
Generally, don't ever call nextLine. It doesn't do what you think it does, and what it does do, is almost entirely useless. Yes, it shows up in every tutorial under the sun.1
Just call .next() if you want a string.
Thus, here, you should be invoking next() to read strings, and nextDouble to read doubles. Except you have utterly bizarre input, where sometimes commas show up and sometimes dots, to separate inputs. Did you make a typo when copying this over? If this is indeed your input, you can only use next(), and then you ahve to massage this broken crazy input first before turning it into numbers.
Also, you don't ever want to use float either. Just use double2. For everything. No it is not 'less efficient' or 'takes more memory'. It's just better, for free.
That was a typo, the input is consistent.
Ensure the scanner has the proper locale set, otherwise it will be expecting a , as separator instead of a . or vice versa. Failure to set locale means that your app will randomly not work depending on the configuration of the host system you're on, you usually do not want that. Use scanner.useLocale(Locale.ENGLISH) for example to do this.
Then:
name = scanner.next(); // returns "sometext"
for (int j = 0; j < numNumbers; j++) {
numbers.add(scanner.nextDouble());
}
It really is that mixed crazy
Then instead of .nextDouble:
String raw = scanner.next();
raw = raw.replace(",", ".");
numbers.add(Double.parseDouble(raw));
You also have a bug
Java is pass-by-value, but numbers is a reference. It's like me handing you, on a note, an _address to a building, and then me driving over there and burning the place to cinders. It doesn't matter that the address I gave you was written on a copied piece of paper you drove off with. If you follow your personal copy of that address, you still find a burnt out house.
So, when you write numbers.clear(), you're removing the numbers from that newly created city. What you want instead of numbers.clear(), which is java-ese for: "Take the piece of paper that you named numbers, which has an address written on it. Drive over there. Burn the house down.", and replace it with: numbers = new ArrayList<Double>() which is java-ese for: "Build a new house on a free spit of land. Take your piece of paper called numbers, and erase whatever is written on there. Now jot down the address to this newly built house.".
You want the second thing. Remember, . is java-ese for: Drive to the address written on here, and = is: Mess with the address itself, do not drive anywhere.
1] You don't need to follow this reasoning to use Scanner, but for those who'd like to know why I say this: Mixing nextLine and nextAnythingElse causes the dreaded problem where you generally just get an empty string back with nextLine. You can invoke a 'blank' nextLine (don't assign it to anything), but then your input processing is broken if the user ever hits that really big, centrally placed key on their keyboard, so that seems like a bad move, even if it is common advice. The real solution is to update the delimiter to \\R, but once you've done that, you don't need nextLine to read lines, just next will do it. Using only nextLine does work fine, but if that's what you want, just.. make a BufferedReader instead, Scanner is overkill. Conclusion: There are no scenarios where nextLine ever makes sense.
2] If some protocol explicitly says to use float, or you know all about IEEE style floating point numbers, you know enough to know when you can ignore this advice. Until you do, heed it.
This code will do the trick:
for(int i = 0 ; i < numLines ; i++){
name = scanner.next();
for(int j = 0 ; j < numNumbers ; j++){
numbers.add(scanner.nextFloat());
}
cities.add(new City(name, numbers));
numbers.clear();
}
I have a string that needs to be compared to the names that are on the website. So the first thing I do is get the number of rows (because some arrays have more or fewer than 2 people in them) and then put that size into an int. String[] names come from the names that selenium is supposed to find when it goes to the website to execute this statement assertTrue(assertion.getText().contains(names[i-1])); The problem is: if the names do not appear in the order in which they appear in the array it breaks. In other words, if Mick Jagger is in li[1] and Keith Richards is in li[2], everything runs as expected. But if Keith Richards appears in li[1] it breaks. Furthermore, I am supposed to use the assertTrue command to do this. I have tried sorting, pushing whats on the web into a new ArrayList and I keep getting errors. Anyone know a good way to ensure the order isn't important and still use the assertTrue command?
Thanks,
Scott
WebElement assertion = null;
List<WebElement> assignees = driver.findElements(By.xpath(".//*[#id='assignee']/li"));
int count = assignees.size();
String[] names = {"Mick", "Keith"};
for (int i = 1; i < count; i++)
{
assertion = driver.findElement(By.xpath(".//*[#id='assignee']/li["+i+"]"));
assertTrue(assertion.getText().contains(names[i-1]));
If names represents the full string, you can just flip it. Make sure the text in your assertion (probably should be named something like assignee instead of assertion) is contained in your collection:
assertTrue(Arrays.asList(names).contains(assertion.getText());
Let me know if this won't work because a name is actually a subset of the text in assertion and I'll adjust the answer.
If they don't exactly match (which you have indicated they don't), you could use linq in c# to match this. Since you're using java you can use an additional loop. There may be a more efficient way to do this in java that I'm not aware of.
String assigneeText = assertion.getText();
boolean nameFound = false;
for(String name: names)
{
nameFound = assigneeText.contains(name);
if(nameFound)
{
break;
}
}
assertTrue(nameFound, "None of the expected names were found in the following assignee text: " + assigneeText);
I am using setname to define buttons in my Swing applcation. I want to use the names in my FEST code. This is the source code:
for (int i = 0; i < trimSizeButtons.length; ++i) {
trimSizeButtons[i].setActionCommand(
trimSizes[i].getDisplayName
trimSizeButtons[i].setName(trimSizes[i].getDisplayName());
What then is the result of the names here so that I can use in my fest code?
That is impossible to answer with the given information.
trimSizes is an array of objects of some type. Those objects (most likely) have an instance variable named displayName. From the code snippet you posted, it is impossible to know what these variables contain.
You could try adding System.out.println("Name of button " + i + " is: " + trimSizes[i].getDisplayName()); to the for loop you posted. This would make the application print the names of all trimSizeButtons to the standard output stream when the application is run.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I've searched for this, but couldn't find an answer and for whatever reason I was too ashamed to ask professor, due to that feeling when hundreds of people stare at you...
Anyhow, my question is what's the importance of having brackets? Is it OK if I omit them? Example:
for (int i = 0; i < size; i++) {
a += b;
}
vs
for (int i = 0; i < size; i++)
a += b;
I know both of them will work, but if I omit the brackets (which I tend to do a lot, due to visibility) will that change anything, anything at all? As I said, I know it works, I tested it dozen of times, but now some of my uni assignments are getting larger, and for some reason I have irrational fear that in the long run, this my cause some problems? Is there a reason to fear that?
It won't change anything at all apart from the maintainability of your code. I've seen code like this:
for (int i = 0; i < size; i++)
a += b;
System.out.println("foo");
which means this:
for (int i = 0; i < size; i++)
a += b;
System.out.println("foo");
... but which should have been this:
for (int i = 0; i < size; i++) {
a += b;
System.out.println("foo");
}
Personally I always include the brackets to reduce the possibility of confusion when reading or modifying the code.
The coding conventions at every company I've worked for have required this - which is not to say that some other companies don't have different conventions...
And just in case you think it would never make a difference: I had to fix a bug once which was pretty much equivalent to the code above. It was remarkably hard to spot... (admittedly this was years ago, before I'd started unit testing, which would no doubt have made it easier to diagnose).
Using braces makes the code more maintainable and understandable. So you should consider them by default.
I sometimes skip using braces on guard clauses to make the code more compact. My requirement for this is that they're if statements that are followed by a jump statement, like return or throw. Also, I keep them in the same line to draw attention to the idiom, e.g:.
if (!isActive()) return;
They also apply to code inside loops:
for (...) {
if (shouldSkip()) continue;
...
}
And to other jump-conditions from methods that are not necessarily at the top of the method body.
Some languages (like Perl or Ruby) have a kind of conditional statement, where braces don't apply:
return if (!isActive());
// or, more interestingly
return unless (isActive());
I consider it to be equivalent to what I just described, but explicitly supported by the language.
There is no difference. The main problem with the second version is you might end up writing this:
for (...)
do_something();
do_something_else();
when you update that method, thinking that do_something_else() is called inside the loop. (And that leads to head-scratching debug sessions.)
There is a second problem that the brace version doesn't have, and its possibly even harder to spot:
for (int i=0; i<3; i++);
System.out.println("Why on earth does this print just once?");
So keep the braces unless you have a good reason, it is just a few keystrokes more.
I think that loosing curly braces is good, if you are also using auto-format, because than your indentation is always correct, so it will be easy to spot any errors that way.
Saying that leaving the curly braces out is bad, weird or unreadable is just wrong, as whole language is based on that idea, and it's pretty popular (python).
But I have to say that without using a formatter it can be dangerous.
For most cases, the answers mentioned so far are correct. But there are some disadvantages to it from the security perspective of things. Having worked in a payments team, security is a much stronger factor that motives such decisions. Lets say you have the following code:
if( "Prod".equals(stage) )
callBankFunction ( creditCardInput )
else
callMockBankFunction ( creditCardInput )
Now lets say you have this code is not working due to some internal problem. You want to check the input. So you make the following change:
if( "Prod".equals(stage) )
callBankFunction ( creditCardInput )
else
callMockBankFunction ( creditCardInput )
Logger.log( creditCardInput )
Say you fix the problem and deploy this code (and maybe the reviewer & you think this won't cause a problem since its not inside the 'Prod' condition). Magically, your production logs now print customer credit card information that is visible to all the personnel who can see the logs. God forbid if any of them (with malicious intent) gets hold of this data.
Thus not giving a brace and a little careless coding can often lead to breach of secure information. It is also classified as a vulnerability in JAVA by CERT - Software Engineering Institure, CMU.
If you have a single statement you can omit the brackets, for more that one statements brackets is necessary for declaring a block of code.
When you use brackets you are declaring a block of code :
{
//Block of code
}
The brackets should be used also with only one statement when you are in a situation of nested statement for improve readability, so for example :
for( ; ; )
if(a == b)
doSomething()
it is more readable written with brackets also if not necessary :
for( ; ; ) {
if(a == b) {
doSomething()
}
}
If you use brackets your code is more readable.
And if you need to add some operator in same block you can avoid possible errors
Using the brackets future proofs the code against later modifications. I've seen cases where brackets were omitted and someone later added some code and didn't put the brackets in at that time. The result was that the code they added didn't go inside the section they thought it did. So I think the answer is that its good practice in light of future changes to the code. I've seen software groups adopt that as a standard, i.e. always requiring brackets even with single line blocks for that reason.
using redundant braces to claim that code is more maintainable raises the following question: if the guys writing, wondering about and further maintaining the code have issues like the ones described before (indentation related or readability related) perhaps they should not program at all...
Nowadays, it is very easy to re-indent codes to find out which block of codes is in which if or for/while. If you insist that re-indenting is hard to do, then brackets placed at wrong indentation can confuse you equally badly.
for(int i = 0; i < 100; i++) { if(i < 10) {
doSomething();
} else { for(int j = 0; j < 5; j++) {
doSomethingElse();
}
}}
If you do this everywhere, your brain is going to break down in no time. Even with brackets, you are depending on indentation to visually find the start and end of code blocks.
If indentation is important, then you should already write your code in correct indentation, so other people don't need to re-indent your codes to read correctly.
If you want to argue that the previous example is too fake/deliberate, and that the brackets are there to capture careless indentation problem (especially when you copy/paste codes), then consider this:
for(int i = 0; i < 100; i++) {
if(i < 10) {
doSomething();
}
else {
for(int j = 0; j < 5; j++) {
doSomethingElse();
}
}
Yes, it looks less serious than the previous example, but you can still get confused by such indentation.
IMHO, it is the responsibility of the person writing the code to check through the code and make sure things are indented correctly before they proceed to do other things.
More support for the "always braces" group from me. If you omit braces for single-statement loops/branches, put the statement on the same line as the control-statement,
if (condition) doSomething();
for(int i = 0; i < arr.length; ++i) arr[i] += b;
that way it's harder to forget inserting braces when the body is expanded. Still, use curlies anyway.
If you remove braces, it will only read the first line of instruction. Any additional lines will not be read. If you have more than 1 line of instruction to be executed pls use curly brace - or else exception will be thrown.
Result wise , it is the same thing.
Only two things to consider.
- Code Maintainability
- Loosely coupled code. (may execute
something else. because you haven't specified the scope for the loop. )
Note: In my observation, if it is loop with in a loop. Inner Loop without braces is also safe. Result will not vary.
If you have only one statement inside the loop it is same.
For example see the following code:
for(int i=0;i<4;i++)
System.out.println("shiva");
we have only one statement in above code. so no issue
for(int i=0;i<4;i++)
System.out.println("shiva");
System.out.println("End");
Here we are having two statements but only first statement comes into inside the loop but not the second statement.
If you have multiple statements under single loop you must use braces.
it should be a reflex to reformat the code as well... that is of course for professional programmers in professional teams
It's probably best to use the curly braces everywhere for the simple fact that debugging this would be an extreme nuisance. But other wise, one line of code doesn't necessarily need the bracket. Hope this helps!
I am trying to retrieve the data from the table and convert each row into CSV format like
s12, james, 24, 1232, Salaried
The below code does the job, but takes a long time, with tables of rows exceeding 1,00,000.
Please advise on optimizing technique:
while(rset1.next()!=false) {
sr=sr+"\n";
for(int j=1;j<=rsMetaData.getColumnCount();j++)
{
if(j< 5)
{
sr=sr+rset1.getString(j).toString()+",";
}
else
sr=sr+rset1.getString(j).toString();
}
}
/SR
Two approaches, in order of preference:
Stream the output
PrintWriter csvOut = ... // Construct a write from an outputstream, say to a file
while (rs.next())
csvOut.println(...) // Write a single line
(note that you should ensure that your Writer / OutputStream is buffered, although many are by default)
Use a StringBuilder
StringBuilder sb = new StringBuilder();
while (rs.next())
sb.append(...) // Write a single line
The idea here is that appending Strings in a loop is a bad idea. Imagine that you have a string. In Java, Strings are immutable. That means that to append to a string you have to copy the entire string and then write more to the end. Since you are appending things a little bit at a time, you will have many many copies of the string which aren't really useful.
If you're writing to a File, it's most efficient just to write directly out with a stream or a Writer. Otherwise you can use the StringBuilder which is tuned to be much more efficient for appending many small strings together.
I'm no Java expert, but I think it's always bad practice to use something like getColumnCount() in a conditional check. This is because after each loop, it runs that function to see what the column count is, instead of just referencing a static number. Instead, set a variable equal to that number and use the variable to compare against j.
You might want to use a StringBuilder to build the string, that's much more efficient when you're doing a lot of concatenation. Also if you have that much data, you might want to consider writing it directly to wherever you're going to put it instead of building it in memory at first, if that's a file or a socket, for example.
StringBuilder sr = new StringBuilder();
int columnCount =rsMetaData.getColumnCount();
while (rset1.next()) {
sr.append('\n');
for (int j = 1; j <= columnCount; j++) {
sr.append(rset1.getString(j));
if (j < 5) {
sr.append(',');
}
}
}
As a completely different, but undoubtely the most optimal alternative, use the DB-provided export facilities. It's unclear which DB you're using, but as per your question history you seem to be doing a lot with Oracle. In this case, you can export a table into a CSV file using UTL_FILE.
See also:
Generating CSV files using Oracle
Stored procedure example on Ask Tom
As the other answers say, stop appending to a String. In Java, String objects are immutable, so each append must do a full copy of the string, turning this into an O(n^2) operation.
The other is big slowdown is fetch size. By default, the driver is likely to fetch one row at a time. Even if this takes 1ms, that limits you to a thousand rows per second. A remote database, even on the same network, will be much worse. Try calling setFetchSize(1000) on the Statement. Beware that setting the fetch size too big can cause out of memory errors with some database drivers.
I don't believe minor code changes are going to make a substantive difference. I'd surely use a StringBuffer however.
He's going to be reading a million rows over a wire, assuming his database is on a separate machine. First, if performance is unacceptable, I'd run that code on the database server and clip the network out of the equation. If it's the sort of code that gets run once a week as a batch job that may be ok.
Now, what are you going to do with the StringBuffer or String once it is fully loaded from the database? We're looking at a String that could be 50 Mbyte long.
This should be 1 iota faster since it removes the unneeded (i<5) check.
StringBuilder sr = new StringBuilder();
int columnCount =rsMetaData.getColumnCount();
while (rset1.next()) {
for (int j = 1; j < columnCount; j++) {
sr.append(rset1.getString(j)).append(",");
}
// I suspect the 'if (j<5)' really meant, "if we aren't on the last
// column then tack on a comma." So we always tack it on above and
// write the last column and a newline now.
sr.append(rset1.getString(columnCount)).append("\n");
}
}
Another answer is to change the select so it returns a comma-sep string. Then we read the single-column result and append it to the StringBuffer.
I forget the syntax now, but something like:
select column1 || "," || column2 || "," ... from table;
Now we don't need to loop and comma concatenation business.
StringBuilder sr = new StringBuilder();
while (rset1.next()) {
sr.append(rset1.getString(1)).append("\n");
}
}