I'm trying to simplify the following code.
while(results.next())
for(String column : colNames){
if(EmptyUtil.isEmpty(results.getString(column))) {
emptyCount++;
}
}
if(emptyCount == colNames.size()){
break;
}
}
My main goal is to read a CSV file until an empty row and finish reading the file from there. And it's a necessity that I have to use this Csvjdbd driver ).
In the above code, results is a CsvResultSet (I've used Csvjdbc library to get this result set ). This CsvResultSet represents a single row in the CSV file inside the for loop. Basically I'm going through every row in the CSV file
b
colNames is the column headers list in the CSV. By using results.toString(column), I can get the value in the particular cell in the row.
If all the cells are empty in the row, I should break from the while loop.
The above code works as expected. I just need to know how to simplify that more.
Try this.
L: while(results.next()) {
for(String column : colNames){
if(!EmptyUtil.isEmpty(results.getString(column))) {
continue L;
}
}
// all the cells are empty in the row
break;
}
Not sure this is much simpler, but perhaps more readable:
while (results.next() && !allColumnsEmpty(results, colNames)) {
}
...
private boolean allColumsEmpty(ResultSet results, String...colNames) {
for(String column : colNames){
if(!EmptyUtil.isEmpty(results.getString(column))) {
return false;
}
}
return true;
}
I would use Stream API to decide, and an external variable instead of break.
boolean wasEmptyRow = false;
while (!wasEmptyRow && results.next()) {
wasEmptyRow = colNames
.stream()
.map(column -> results.getString(column))
.allMatch(EmptyUtil::isEmpty);
if (! wasEmptyRow) {
// process
}
}
You simply create a stream from the column names, replace all values with the current value from the result, then check if all of them are empty.
The allMatch is optimized, it will not check all columns if one failing case was found. This saves the break for you.
Related
Here's my current code snippet:
Iterable<HashMap<String, EntityProperty>> results =
cloudTable.execute(query, propertyResolver);
if (results == null) {
System.out.println("No files processed");
exit_code = "exit_code=1";
} else {
for (HashMap<String, EntityProperty> entity : results) {
// don't know how to start the loop here
}
}
I have a query for retrieving a list of certain files in Microsoft Azure. Now I just need to show the number of files processed result.
I know the concept of what I should be doing, create a counter within the for loop, and then after the Iterations in that loop, whatever the value of that counter variable, it should also give me the count of files right? I just don't know how to start :( I've been reading so much about Iterable in Java but still can't get a grasp on how it would work.
Any inputs would be greatly appreciated
Like this?
Iterable<HashMap<String, EntityProperty>> results =
cloudTable.execute(query, propertyResolver);
int counter;
if (results == null) {
System.out.println("No files processed");
exit_code = "exit_code=1";
} else {
counter = 0;
for (HashMap<String, EntityProperty> entity : results) {
// don't know how to start the loop here
counter++;
}
//int size = results.size();
}
new to JavaFX, and been trying to get a TableView cell's position by row, col indices. Looking for something like Swing's JTable.getCellRect;
I've seen solutions for the case where a specific cell's value is needed,
(JavaFX Simplest way to get cell data using table index)
I've also figured it would be enough to get the TableCell of the corresponding row and column, then get bounds and use localToScreen etc, but couldn't find a way to get a specific table-cell as well.
Would love any help with any of that.
Thanks in advance
There's no direct way to do this in JavaFX, by design. Since cells are only created for data that is currently visible, and are reused (for example as the user scrolls around the table), there isn't a 1-1, or even a consistent, relationship between any given cell and the "location" in the table's backing data. Consequently, you really should not even attempt to find a cell for a given data item, and should try to find another approach to whatever you are trying to do.
(From a MVC design approach, this makes sense too: you are asking to find the view (cell) from the model (data); the model is supposed to be completely unaware of the view.)
If you really want to attempt this (and, in case it's not clear, I think you should find another approach), you can try to keep track of the cells for each position as they change, using something like the following:
TableView<SomeDataType> table = new TableView<>();
Map<TableColumn<SomeDataType, ?>, Map<Number, TableCell<SomeDataType, ?>>> cells = new HashMap<>();
TableColumn<SomeDataType, SomeColumnDataType> column = new TableColumn<>(...);
cells.put(column, new HashMap<>();
column.setCellValueFactory(...);
column.setCellFactory(tc -> {
TableCell<SomeDataType, SomeColumnDataType> cell = new TableCell<SomeDataType, SomeColumnDataType>() {
#Override
protected void updateItem(SomeColumnDataType item, boolean empty) {
super.updateItem(item, empty) ;
if (empty) {
setText(null);
} else {
setText(item.toString());
}
}
};
cell.indexProperty().addListener((obs, oldIndex, newIndex) -> {
if (oldIndex != null) {
cells.get(column).remove(oldIndex);
}
if (newIndex != null && newIndex.intValue() != -1) {
cells.get(column).put(newIndex, cell);
}
});
return cell ;
});
// repeat for other columns...
Then you can do
TableCell<SomeDataType, ?> cell = cells.get(someColumn).get(someIndex);
to get a cell for a specific column and row index. Note that you need to check for null (if that data doesn't currently have a cell).
This will probably need very careful debugging, but the approach should work.
Update: I made an SSCCE using this technique here.
You could also try via a lookup. Lookups are not very robust, and won't work at all until CSS has been applied to the scene graph, but you can try something like this:
TableColumn<...> columnOfInterest = ... ;
int rowIndexOfInterest = ... ;
TableCell<?, ?> cell = null ;
for (Node n : table.lookupAll(".table-cell")) {
TableCell<?,?> c = (TableCell<?,?>) n ;
if (c.getTableColumn() == columnOfInterest
&& c.getIndex() == rowIndexOfInterest) {
cell = c ;
break ;
}
}
if (cell != null) {
// ...
}
or in a more Java 8 approach:
table.lookupAll(".table-cell").stream()
.map(TableCell.class::cast)
.filter(c -> c.getTableColumn() == columnOfInterest && c.getIndex() == rowIndexOfInterest)
.findAny()
.ifPresent(cell -> {
// do whatever you need with the cell....
});
I want to get data from Excel file. I'm using while loop, iterator and hasNext() method to go by all rows.
My problem: sometimes after rows with data there are empty rows (propably with cell type string and value "" or null), which I don't want to iterate by.
So I added method isCellEmpty():
public static boolean isCellEmpty(final Cell cell) {
if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
return true;
}
if (cell.getCellType() == Cell.CELL_TYPE_STRING && cell.getStringCellValue().isEmpty()) {
return true;
}
return false;
}
and added it after starring while loop in main method:
while (rowIterator.hasNext()) {
row = rowIterator.next();
if (isCellEmpty(row.getCell(2))) {
break;
}
// some code ...
}
But now I have a break statement. How can I iterate by all not empty rows without using break or continue? Now (with break) my algorithm is working properly - I'm getting data which I need. I'm just wondering if it's possible to write code without break or continue.
If you want to keep your while loop, and avoid a break, the easiest is probably a status boolean, eg
boolean inData = true;
while (rowIterator.hasNext() && inData) {
row = rowIterator.next();
if (row == null || isCellEmpty(row.getCell(2))) {
inData = false;
} else {
// Use the row
}
}
Otherwise, I'd suggest reading the Apache POI documentation on iterating over rows and cells, there are other approaches you could take which might work even better!
Oh, and don't forget that rows can be null, so you need to check that before you try fetching the cell
Looks like POI have no enanchements or features to iterate just over non-empty rows.
POIS' devs posted about this subject. Check out Apache POI HSSF+XSSF sections Iterate over rows and cells and Iterate over cells, with control of missing / blank cells
Note that POI works with Iterators, so instead of loops, I would use Apache IteratorUtils from Apache Commons Collections, which is likely to be alredy in your classpath due to some transitive dependency.
In order to make your code cleaner and readable, the solution would be similiar to
import org.apache.commons.collections.Predicate;
public class ValidRowPredicate implements Predicate{
#Override
public boolean evaluate(Object object) {
Row row = (Row) object;
Cell cell = row.getCell(2);
if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
return false;
} else if (cell.getCellType() == Cell.CELL_TYPE_STRING &&
cell.getStringCellValue().isEmpty()) {
return false;
}
return true;
}
}
The consumer would looks like
Iterator<Row> rawIterator = rowIterator;
Iterator<Row> cleanIterator = IteratorUtils.filteredIterator(rawIterator , new ValidRowPredicate());
while(cleanIterator.hasNext()){
Row row = cleanIterator.next();
// some code
}
You might belive that we are iterating book 2 times but we aren't.
The first loop does, but further iterations are over a subset of valid rows. Additionaly, we made reusable the validation of empty cell #2.
We also got a reliable Iterator which only have valid and computable entries.
Predicates gives lot of possibilites. Like chaining Predicats by inheritance or composition.
Its cost is in infact, the first loop all over the main Iterator. But the result worth it.
IteratorUtils as CollectionUtils are really good utils that we often have'm in the classpath but we ignore.
Not sure if I get the question right, are you looking for something like this?
Row row;
while (rowIterator.hasNext()
&& !isCellEmpty((row = rowIterator.next()).getCell(2))) {
// do something with row
}
This would process all rows until it finds an empty cell and ends the loop.
You have several options to exit a loop without using break:
Use some other control flow, e.g. return, throw;
Add an extra condition to the loop guard:
boolean shouldContinue = true;
while (shouldContinue && rowIterator.hasNext()) {
row = rowIterator.next();
if (isCellEmpty(...)) {
shouldContinue = false;
}
}
Exhaust the iterator inside the loop body:
while (rowIterator.hasNext()) {
row = rowIterator.next();
if (isCellEmpty(...)) {
while (rowIterator.hasNext()) rowIterator.next();
}
}
Or just use break. It's not so bad.
Change your function isCellEmpty() use switch than a nested if-else.
public static boolean isCellEmpty(final Cell cell) {
switch(cell.getCellType()){
case Cell.CELL_TYPE_BLANK :
case cell.CELL_TYPE_STRING :
if(StringUtils.isBlank(cell.getCellValue())
return true;
else
return false;
break;
default :
return false;
break;
}
}
Now use this code
boolean hasCellData= true;
while (rowIterator.hasNext() && hasCellData) {
row = rowIterator.next(); //iterate through each rows.
if (row == null || isCellEmpty(row.getCell(2))) {
hasData = false;
} else {
//if row contains data then do your stuffs.
}
}
This while (rowIterator.hasNext() && hasCellData) loop will stop at point of time if a row contains null values. It never check whether beyond of this row have some data.
Example :- Suppose In your sheet data is filled from row 1 to 50 but in between there is a row number 30 which is blank then this will not Iterate after row number 30.
Thanks.
Might be too simplistic but wouldn't the following be enough?
while (rowIterator.hasNext()) {
row = rowIterator.next();
if (!isCellEmpty(row.getCell(2))) {
// some code ...
}
}
If we would like to stop the iteration once an empty row/cell is encountered the following approach could be taken:
for(boolean shouldContinue = true; shouldContinue && rowIterator.hasNext(); ) {
if (!isCellEmpty(row.getCell(2))) {
// some code ...
} else {
shouldContinue = false;
}
}
Able to remove empty rows based on the Laiv's answer's. I've modified to support passing the Row. This is the modified answer
import org.apache.commons.collections4.Predicate;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
public class ValidRowPredicate implements Predicate<Row> {
#Override
public boolean evaluate(Row row) {
Cell cell = row.getCell(2);
if (cell == null || cell.getCellType() == CellType.BLANK) {
return false;
} else if (cell.getCellType() == CellType.STRING &&
cell.getStringCellValue().isEmpty()) {
return false;
}
return true;
}
}
Credits goes to Laiv
Note: Little long question. I'm going to give a bounty for best answer.
What I'm trying to do is querying on Object. Here is the details. I have a file called employee.txt. So I parsed it and kept in the list
public static List<Employee> employeeList = new LinkedList<>();
Then here is my logic to query.
Take the query from user, and then parse it. The below is the logic to query through the list.
For ex: here is the query
select * from Employee where id > 10
My codes for that
String valueToCompare = split[5]; //10
EmployeeCriteria criteria = new EmployeeCriteria(
isId, isName, isSalary, expression,
valueToCompare);
result = EmployeeData.findAll(
EmployeeData.employeeList, criteria);
Here is the findAll method
public static List<Employee> findAll(List<Employee> coll,
ISearch<Employee> chk) {
List<Employee> l = new LinkedList<Employee>();
for (Employee obj : coll) {
if (chk.search(new Employee(obj)))
l.add(obj);
}
return l;
}
And here is my search method
/**
* Based on the type provided and for given expression it check against the
* given value
*/
#Override
public boolean search(Employee obj) {
if (expression.equals(EQUAL)) {
if (isId()) {
if (obj.getId() == Long.parseLong(valueToCompare)) {
return true;
}
} else if (isName()) {
if (obj.getName().equals(valueToCompare)) {
return true;
}
} else if (isSalary()) {
if (obj.getSalary() == Long.parseLong(valueToCompare)) {
return true;
}
} else {
System.err.println(UserMessage.INVALIDCOLUMN_NAME);
}
} else if (expression.equals(NOT_EQUAL)) {
if (isId()) {
if (!(obj.getId() == Long.parseLong(valueToCompare))) {
return true;
}
} else if (isName()) {
if (!(obj.getName().equals(valueToCompare))) {
return true;
}
} else if (isSalary()) {
if (!(obj.getSalary() == Long.parseLong(valueToCompare))) {
return true;
}
} else {
System.err.println(UserMessage.INVALIDCOLUMN_NAME);
}
} else if (expression.equals(GREATER)) {
if (isId()) {
if ((obj.getId() > Long.parseLong(valueToCompare))) {
return true;
}
} else if (isSalary()) {
if ((obj.getSalary() > Long.parseLong(valueToCompare))) {
return true;
}
} else {
System.err.println(UserMessage.INVALIDCOLUMN_NAME);
}
} else if (expression.equals(LESSER)) {
if (isId()) {
if ((obj.getId() < Long.parseLong(valueToCompare))) {
return true;
}
} else if (isSalary()) {
if ((obj.getSalary() < Long.parseLong(valueToCompare))) {
return true;
}
} else {
System.err.println(UserMessage.INVALID_IDENTIFIER);
}
}
return false;
}
Let me know if you want to see any other codes.
I just want to know,
In the first place LinkedList is correct data structure to use ? Is this performs well ?? Any enhancements to perform well ?
Any better way to achieve this ?
here are few example queries:
select * where ID > 100
select * where Name != Ramesh
select * where Salary < 500000
select Name order by Name
select ID
Thanks for any help. Bounty will be offered after 2 days. I can't do that now.
Note2: This is a test to check my data manage skills and I cannot use any database.
No, this does not perform well at all. You are searching through N employees every time. So if you have 1 million employees, you will search all 1 million employees before returning the correct employee. Even worst, if it doesn't exist, you will have to search exhaustibly before you can know if it exists.
Is this for use in production? If so then just use SQLite or some other simple database. You want to write once and read multiple times with indexes. I cannot stress enough that what you are writing will have bugs and instead you should use something that was already tested.
Assuming this is not for production and you are just having fun, then you want to emulate what databases do in real life. They create indexes. Indexes are usually best described as Map<String, List<Employee>>.
The idea is that initially reading the data from disk is expensive. But you read it once. For each dimension, Name, Salary, ID, etc... you want create separate indexes.
So let's say you were creating an index of all employees by ID. You would want to do something like:
Map<String, Employee> employeesById = new HashMap<>();
for(Employee e : employees) {
employeesById.put(e.getId(), e);
}
The above assumes that employee ids are unique. If they are not then you would need create a List<Employee>. For example for index by name:
Map<String,List<Employee>> employeesByName = new HashMap<>();
for(Employee e : employees) {
employeesByName.get(e.getName()).add(e); // Make sure to create the array if it doesn't exist
}
So now, for reading, let's say you get SELECT * FROM employees where id = 123; you can simply just return employeesById.get("123").
This solution is O(1). As the file gets bigger, you will not have any performance loss. This is probably the fastest solution.
To add onto Amir's answer, you can also use a TreeMap<> instead of a HashMap<>. Databases normally don't create indexes as hash maps but as balanced binary trees, which is what Java's TreeMap<> class is.
http://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html
HashMap<> has O(1) lookup on keys, but is exact match on key only. TreeMap<> has O(log n) lookup on keys, but allows ranged lookups higherKey, lowerKey) and map partitioning on key range (subMap).
The problem of duplicates can either be solved by not allowing them (unique key) or storing values in a list and linear search on the subset (non-unique key).
Assuming you are not interested in any of the in-memory database solution and using Java 8,
You should convert all your conditions to predicate and apply them on the stream . This will take advantage of Java 8's parallelism feature http://blog.takipi.com/new-parallelism-apis-in-java-8-behind-the-glitz-and-glamour/
So in short your code can be much cleaner and faster
public static Predicate<Employee> isSalaryGreaterThan(Integer salary) {
return p -> p.getSalary() > salary;
}
Predicate predicate1 = isSalaryGreaterThan(50000)
employeeList.stream().filter(predicate1).filter(predicate2)...collect(Collectors.<Employee>toList())
some part deleted. that may not necessary now.
I am using following code, My main intention is if condition matched then exit from the loop and return expected data .
In Below list , where i am getting actual expected list but could not return data, what i am want. I am returning testting data value.
public String getlistdata(){
String s = "testting data";
if(!(this.element==null)){
ListIterator<ElementData> li = this.element.listIterator();
List<String> list = new ArrayList<String>();;
while (li.hasNext()) {
list.add(li.next().getElemType().toString());
}
Log.e("LIST", "TEST LIST"+list+"=="+list.size());
for (String temp : list) {
System.out.println(temp);
if (temp.toString().equalsIgnoreCase("group")){
s = li.next().getGrpResult();
break ;
}
}
}
return s;
}
please identify where i am doing wrong with this code.
Edited:
I solve above problem of user2310289 answers which is below but problem i have another problem here again
I have problem, if i have two or more group here, all time executed
first group. How to execute second time this method call next group.
or third time third group. it means how to start this if second time
call this function, starting index from first groupindex+1 and third
call this method second groupindex+1 and so on. I have lots of
confusing here. aspect ting some hint
text, group, group, normal, number, group, text
Instead of break use return s.
if (temp.toString().equalsIgnoreCase("group")){
s = li.next().getGrpResult();
return s ;
}
Why even bother adding the data to a local List in will never be re-used.
Updated
Also
Firstly the code while (li.hasNext()) { iterates right through the list and later it attempts to li.next().getGrpResult(); A NoSuchElementException will be thrown - as the iteration has no next element
try
String s = "testing data";
if(!(this.element==null)){
ListIterator<ElementData> li = this.element.listIterator();
while (li.hasNext()) {
ElementData ed = li.next();
String temp = ed.getElemType().toString();
System.out.println(temp);
if (temp.equalsIgnoreCase("group")){
return ed.getGrpResult ();
}
}
}
return null;
Update
Further to your comment, if you want all matching ElementData then instead of return ed.getGrpResult(); simply add to an ArrayList myList.add (ed.getGrpResult ()); and then the code will continue looping. At the end of the method return the ArrayList.
Just make following change to if condition,
if (temp.toString().equalsIgnoreCase("group")){
s = li.next().getGrpResult();
return s;
}