Above is my database in Firestore. As can be seen, there are 2 Strings and 2 (or more) Arrays as fields.
I will be fetching the data to convert the same into different graphs
For ex: 1. Graph showing sum of all chapters of all users
2. Graph showing sum of "chapter1" of all users.
3. Graph showing averages of all chapters etc.,
These graphs will be in different activities based on the selection of the user and the calculations are done specific to that activity.
Now my issue is in accessing this data to use it in various activities.
I have tried the HashMap Map> to store phonenumb, chapter(x), and values of chapter(x) respectively.
Below is the code to access the data:
CollectionReference chemistry = db.collection("RESULTS").document("Summary").collection("ChemistryVII");
chemistry
.whereEqualTo("school", "Test School")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
for (DocumentSnapshot document : task.getResult()) {
Map<String, Object> map = document.getData();
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getKey().contains("chapter")) {
if (outer.isEmpty() || !outer.containsKey(map.get("phonenumb"))) {
Map<String, Object> inner = new HashMap<>();
inner.put(entry.getKey(), entry.getValue());
String phonenumb = map.get("phonenumb").toString();
outer.put(phonenumb, inner);
} else {
Map<String, Object> inner = new HashMap<>();
inner.put(entry.getKey(), entry.getValue());
String phonenumb = map.get("phonenumb").toString();
outer.put(phonenumb, inner);
}
}
}
}
//Toast("Outer Details " + outer);
schoolGraph();
}
});
However, this will not work as there could be multiple entries for the given key (phonenumb).
Trying to understand the best way to access such data and use it for multiple activities.
Hash map key is unique. Every time you add a new Object with the same key, the old valude with the same key will be overwritten.
I think the logic in this part is correct:
if (outer.isEmpty() || !outer.containsKey(map.get("phonenumb"))) {
Map<String, Object> inner = new HashMap<>();
inner.put(entry.getKey(), entry.getValue());
String phonenumb = map.get("phonenumb").toString();
outer.put(phonenumb, inner);
You insert in the inner map the first chapter sum. Because the outer map does not have the key phonenumb, you need to insert in the outer map too.
However in the else part:
Map<String, Object> inner = new HashMap<>();
inner.put(entry.getKey(), entry.getValue());
String phonenumb = map.get("phonenumb").toString();
outer.put(phonenumb, inner);
You do not need the outer.put(phonenumb, inner);, because inner exists already and has the sum of a chapter.
Here the outer has the key 'phonenumber', you just have to insert to the inner map the new entry sum: inner[chapter] = sum .
You need something like outert[phonenumb][chapter] = sum
Related
I'm trying to delete the todos in the Map data-type (todoDate) I have created.
the Map<String, List> data type variable problem (todoDate) problem:
I want every key in the Map to be deleted but instead what happens is that only the key with index 0 is deleted and the rest remain. Thanks for helping.
String uid = FirebaseAuth.instance.currentUser!.uid.toString();
final todo =
FirebaseFirestore.instance.collection('users').doc(uid).collection('todos');
void Function()? deleteTodoCollection(Map<String, List<String>> todoDate) {
//delete from firebase
todo.get().then((snapshot) {
for (DocumentSnapshot doc in snapshot.docs) {
doc.reference.delete();
}
});
//delete from the todoDate map
for (var key in todoDate.keys) {
todoDate.remove(key);
print(todoDate);
}
return null;
}
try toList()
...
for (var key in todoDate.keys.toList()) {
...
i am a new to spring batch and my requirement is to read a dynamic excel sheet and insert into database.I am able to read excel and pass it to writer but only last record in excel sheet gets inserted into database. Here is my code for item writer
#Bean
public ItemWriter<List<LinkedHashMap<String, String>>> tempwrite() {
JdbcBatchItemWriter<List<LinkedHashMap<String, String>>> databaseItemWriter = new JdbcBatchItemWriter<>();
databaseItemWriter.setDataSource(dataSource);
databaseItemWriter.setSql("insert into table values(next value for seq_table,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
ItemPreparedStatementSetter<List<LinkedHashMap<String, String>>> valueSetter =
new databasePsSetter();
databaseItemWriter.setItemPreparedStatementSetter(valueSetter);
return databaseItemWriter;
}
and below is my prepared statement setter class
public class databasePsSetter implements ItemPreparedStatementSetter<List<LinkedHashMap<String, String>>> {
#Override
public void setValues(List<LinkedHashMap<String, String>> item, PreparedStatement ps) throws SQLException {
int columnNumber=1;
for(LinkedHashMap<String, String> row:item){
columnNumber=1;
for (Map.Entry<String, String> entry : row.entrySet()) {
ps.setString(columnNumber, entry.getValue());
columnNumber++;
}
}
}
}
I have seen many examples but all of them is using a dto class but i am not sure whether this is the correct way of implementation for list of list which contains hashmap
I have a simple table (CellTable) and a TextBox for filter.
Values for CellTable I take from backend. After list of items is loaded I can put some filter string to get suitable result. To filter list from dataprovider I use a predicate. After filtering I set result to CellTable.
Like here:
void onFilterNameKeyUp(KeyUpEvent e) {
List<CustomerDTO> filtered = this.dataProvider.getList();
Predicate<CustomerDTO> filter = new Predicate<CustomerDTO>() {
#Override
public boolean apply(CustomerDTO input) {
if (input.getName() == null) {
return false;
} else {
return input.getName().toLowerCase()
.contains(filterName.getValue().toLowerCase());
}
}
};
filtered = Lists.newArrayList(Iterables.filter(this.dataProvider.getList(), filter));
this.customerList.setRowCount(filtered.size(), true);
this.customerList.setRowData(0, filtered);
}
this.dataProvider = new ListDataProvider<CustomerDTO>();
dataProvider.addDataDisplay(this.customerList);
final ListHandler<CustomerDTO> sortHandler = new ListHandler<CustomerDTO>(
this.dataProvider.getList());
this.customerList.addColumnSortHandler(sortHandler);
this.customerList.getColumnSortList().push(this.rbKeyNameColumn);
Everything work fine but I have also a sort handler for first column of this table and when I want to sort a list then I'm sorting original list of items.
How to solve this problem? It means that I want to sort and display filtered list instead of original list from dataprovider.
Please help.
I have a table changing content after receiving some data from the server. This is my approach:
public void onSuccess(List<List<String>> result) {
List<Product> list = dataProvider.getList();
list.clear();
r_tableproducts.setRowCount(result.size());
for (List<String> l : result) {
list.add(new Product(l));
}
r_tableproducts.getColumnSortList().clear();
r_tableproducts.getColumnSortList().push(r_tableproducts.getColumn(1));
ColumnSortEvent.fire(r_tableproducts,r_tableproducts.getColumnSortList());
}
This sorts my list using 2nd column after reciving new data (overriding all old data).
Maybe try this approach? Filter your data in a new list and modify the list your dataProvider provides you, adding all elements.
Something like:
List<CustomerDTO> result = Lists.newArrayList(Iterables.filter(this.dataProvider.getList(), filter));
this.customerList.setRowCount(result.size(), true);
this.dataProvider.getList().clear();
this.dataProvider.getList().addAll(result);
You need to separate the dataProvider that holds the full list and provide a separate "filtered" data provider that will be driving the display of the cellTable. The cellTable in below example is bound to a filteredDataProvider for sorting, display purposes.
The code below is to give a general idea and therefore may not be syntactically accurate.
void onFilterNameKeyUp(KeyUpEvent e) {
List<CustomerDTO> filtered = this.dataProvider.getList();
Predicate<CustomerDTO> filter = new Predicate<CustomerDTO>() {
#Override
public boolean apply(CustomerDTO input) {
if (input.getName() == null) {
return false;
} else {
return input.getName().toLowerCase()
.contains(filterName.getValue().toLowerCase());
}
}
};
filtered = Lists.newArrayList(Iterables.filter(this.dataProvider.getList(), filter));
this.customerList.setRowCount(filtered.size(), true);
this.filteredDataProvider.getList().clear();
this.filteredDataProvider.getList().addAll(filtered);
}
this.dataProvider = new ListDataProvider<CustomerDTO>();
// Code here to populate the dataProvider
this.filteredDataProvider = new ListDataProvider<CustomerDTO>();
// Creating separate DataProvider to hold the filtered set
this.filteredDataProvider.getList().addAll(this.dataProvider.getList());
filteredDataProvider.addDataDisplay(this.customerList);
// dataProvider.addDataDisplay(this.customerList);
// Sort Handler uses filteredDataProvider instead of the dataProvider with full list
final ListHandler<CustomerDTO> sortHandler = new ListHandler<CustomerDTO>(
this.filteredDataProvider.getList());
this.customerList.addColumnSortHandler(sortHandler);
this.customerList.getColumnSortList().push(this.rbKeyNameColumn);
I create and populate a Guava Table using the following code:
Table<String, String, Integer> table = HashBasedTable.create();
table.put("A", "B", 1);
table.put("A", "C", 2);
table.put("B", "D", 3);
I wonder how to iterate over table and print out both keys and value for each row? So, the desired output is:
A B 1
A C 2
B D 3
Im not Guava user so this may be overkill (if it is true then will be glad for any info) but you can use table.rowMap() to get Map<String, Map<String, Integer>> which will represents data in table in form {A={B=1, C=2}, B={D=3}}. Then just iterate over this map like:
Map<String, Map<String, Integer>> map = table.rowMap();
for (String row : map.keySet()) {
Map<String, Integer> tmp = map.get(row);
for (Map.Entry<String, Integer> pair : tmp.entrySet()) {
System.out.println(row+" "+pair.getKey()+" "+pair.getValue());
}
}
or
for (Map.Entry<String, Map<String,Integer>> outer : map.entrySet()) {
for (Map.Entry<String, Integer> inner : outer.getValue().entrySet()) {
System.out.println(outer.getKey()+" "+inner.getKey()+" "+inner.getValue());
}
}
or even better using com.google.common.collect.Table.Cell
for (Cell<String, String, Integer> cell: table.cellSet()){
System.out.println(cell.getRowKey()+" "+cell.getColumnKey()+" "+cell.getValue());
}
you can use :
System.out.println(Arrays.asList(table));
and the output will be
[{A={B=1, C=2}, B={D=3}}]
I have my datas as a Map<Key,ArrayList<Value>> So i want my col1 to represent my key and the other columns to represent data in my values. And this Value can be or multiple rows. So i was thinking of putting a celltable inside a celltable but then it will affect my headers(since the number of columns for the outer celltable will be just 2) and also the sorting.
And also if i pass the map directly to ListDataProvider it assumes the number of rows is the number of rows of the map but it is not the case.
So what is the best way to do this ?
I'd suggest using a class RowObject like this:
class RowObject {
private final Key key;
private final Value value;
RowObject(Key key, Value value) {
this.key = key;
this.value = value;
}
/* Getters omitted */
}
Then convert the map to a list of RowObjects and feed the list to the data provider:
List<RowObject> rowObjects = new ArrayList<RowObject>();
for (Entry<Key, ArrayList<Value>> entry : map.entrySet()) {
for (Value value : entry.getValue()) {
rowObjects.add(new RowObject(entry.getKey(), value));
}
}
ListDataProvider<RowObject> dataProvider = new ListDataProvider<RowObject>();
dataProvider.addDataDisplay(cellTable);
dataProvider.setList(rowObjects);
Add columns like this:
Column column = new Column<RowObject, String>(new TextCell()) {
#Override
public String getValue(RowObject object) {
return getStringValueFor(object);
}
};
cellTable.addColumn(column);