I have RecyclerView witch initialized with data like this:
data class ObjectData(
var name: String,
var pass: Boolean
) : Serializable
I am Initialing the Adapter with ArrayList. In my Activity I have filter (All, Passed, No Passed). When I click one of the filters I wish that RecyclerView refresh with new data regarding the "pass" value. Example: On "Passed" filter button it will show only ObjectData with pass=true.
Question: What is the best approach to this? I can hold 3 list views, one with all data, one with passed objects and one with unpassed, and update adapter with the needed list when filter is changed. But this will cause data duplication. I can on filter copy all data to new filtered list, but it will trigger copy on every button filter click, and the user may change filters rapidly.
What can you suggest.
I would simply create copies lazily and cache them for example like this:
data class ObjectData(
var name: String,
var pass: Boolean
) : Serializable
val allData: List<ObjectData> = emptyList()
val filteredData: Map<Boolean, List<ObjectData>> by lazy {
allData.groupBy { it.pass }
}
This way you'll create both filtered lists in one go and only when you need them.
Honestly if data set is not big i wouldn't really optimise prematurely unless i see performance is bad. Nowadays Android has much better memory handling.
Related
I want to show data in vaadin's grid, but I want to create columns dynamically for each value from customAttributes list. My data model more or less look like this
Item
name: String
localization: Localization
visible: Boolean
customAttributes: List<CustomAttribute>
CustomAttribute
name: String
value: String
Each Item has the same set of attribute types, only the values are different. User can manually defined new attribute types.
How can I create this grid?
Currently I do it in this way:
grid.setColumns("name", "visible");
grid.addColumn(v -> v.getLocalization().getName()).setHeader("Localization");
But I have no idea for dynamic creating columns for each custom attribute.
Like it was already written in the comments, you can loop over the attribute names assuming your have a list (or set) of them. One small gotcha is that you need to do that in a way that ensures values inside the callback are effectively final.
attributeNames.forEach(name -> {
grid.addColumn(item -> item.getCustomAttributes().get(name))
.setHeader(name);
});
If you don't directly know the attribute names but you're loading all items into memory instead of lazy loading them, then you can find the unique names by iterating over all items:
items.stream().flatMap(item -> item.getCustomAttributes().keySet().stream())
.distinct().forEach(<same loop as in the previous example>);
When I have a list with a bigger amount of elements (around 7000) and I add sorting to the query, change listeners are getting very slow. This is not the case when only one field is given. From the second field it slows down a lot. It also seems to depend on what field type is given to sorting. Booleans seem to be quite fast. Dates are also slower when only one is used.
Let me show you what I do:
very simple query on all objects with multiple sorting elements:
val theList = realm.where(TheObject::class.java)
.sort(
arrayOf("fieldBool", "fieldDate", "fieldString"),
arrayOf(Sort.DESCENDING, Sort.DESCENDING, Sort.DESCENDING)
)
.findAllAsync()
theList.addChangeListener { result: RealmResults<TheObject> ->
// Set the list to the view.
}
Now, when some object in this resulting list is changed, the change listener needs a lot of time to update the data. Also other change listeners on the same looper are very slow.
even if I sort the result after adding a changeListener (in the change lsitener):
val theList = realm.where(TheObject::class.java)
.findAllAsync()
theList.addChangeListener { result: RealmResults<TheObject> ->
viewToSet.list = result.sort(
arrayOf("fieldBool", "fieldDate", "fieldString"),
arrayOf(Sort.DESCENDING, Sort.DESCENDING, Sort.DESCENDING)
)
}
the update happens very slow. I found out that it might has to do with listening to do with calculating the changeset. If I add a changelistener to the realm instead of the result, it works quite fast. Still what is interesting is that I do not add a changeListener to the sorted list but to the unsorted list. sorting then works quite fast inside of the listener, but as soon as I have a sorted RealmResults living somewhere, the changeset creation seems to take a while...
Is this a bug or just a weakness of Realm?
The problem is a comination of two Edgecases/Bugs in realm:
A bug that every living RealmResult will be taken into account when creating changesets, even when the RealmResult itself has no listener (see https://github.com/realm/realm-java/issues/6614).
Realm has an edgecase when an object has cycling references (ObjectA -> ObjectB -> RealmList<ObjectA>) is fetched in a list and that list gets sorted, the changeset creation takes a long time.
I fixed this by removing the cycling reference. Now it works.
I have a piece of code that scrapes a college timetable webpage and generates a list of lists of lists (of lists) like so:
[[[[start_time, end_time], [module_code, period_type, {period_number}], [room_code]], {next modules...}],{next_days...}]
If I wanted to document this kind of returned data in Python (and possibly Java or other languages) would there be a best practice for doing so?
Note: I've looked at PEP but haven't been able to find anything related to this
You create simple classes to hold your data instead of using nested lists:
class TimeTableEntry(object):
def __init__(self, start, end, module, room):
self.start = start
self.end = end
self.module = module
self.room = room
Then document that your method returns a list of those. The added advantage is that now you can add additional methods on these objects. Add a __str__ method for easy display. Etc.
Most of all, you can document these entry objects far more clearly than you could document a nested structure of primitive types.
This sort of structure is better modeled as a dictionary; with the key being the room code. Each room code key holds a list, and this list has tuples that represent each course/event.
schedule = dict()
schedule['room_1'] = [(start_time,end_time,module_code,period_type,..),
(start_time,end_time,module_code,period.....),
...
]
schedule['room_2'] = [ ... ] # as above
This makes it easier to document and also gives you the ability to do things like:
for i in schedule:
print '{0} events scheduled for room {1}".format(len(schedule[i]),i)
Here is how you could possibly document it:
def foo(bar):
'''
Does some magic with `bar`. Cats may be harmed and
the space time continuum may be disturbed if you pass in
silly things like None.
Args:
bar: The best name for a variable since foo.
Returns:
A dict mapping keys to the room and rows representing
the room's schedule. A row is represented as a list.
Each element of the list is a tuple of strings representing
and event. For example:
{'room_1': [(start_time,end_time,module_code,period_type,..)]}
'''
I am working on a videogame with a friend. To account for different types of items, we originally had a class for each item extending an Item class. There wasn't much data in these classes, so I was looking for an alternative so that our workspace wasn't so cluttered. I started learning about HashMaps, and I thought they were an awesome way to add items. We could also set it up so that instead of accessing the items in the HashMap with an int, which would basically just make it an ArrayList, we could access them with Strings. So I started adding this functionality, creating anonymous Items in the Item class,
private static Item coal = new Item() {
weight = .2;
setImageID(0, 16);
}
and adding them to the HashMap.
itemMap.put("Coal", coal);
After doing a few of these, I realized that there was only one item of each type in the list, and if we ever wanted to have multiples of those items that could be modified without modifying the original, we would need to make copies. I started doing research on how to do that. We could use a copy constructor, but there are too many variables in an Item for that to be done efficiently. We certainly could do that, but I was wondering if there was a simple solution. Could we make all of the items final? I'm just spitballing, because I am totally new to this area of programming. We could be doing this whole thing wrong, too. I just need a way to use a HashMap to create something of an "Item database" that I can use to access an indefinite amount of an item in the list. Any suggestions?
How about having a HashMap that has a value of a set (or a list depending on if the same item can exist more than once)?
Map<String, Set<Item>> map = new HashMap<String, Set<Item>>();
That way, you can have multiple items for each type.
One idiom for adding a new item to the type's set is below:
Set<Item> items = map.get(type);
if (items == null) {
items = new HashSet<Item>();
items.put(type, items);
}
items.add(item);
It might not even be a bad idea to use an Enum for your type instead of just a String. Then you could do something like map.put(Item.COAL, itemSet); This would help guard against typos and case sensitivity issues.
Would a Hashmap<string,ArrayList<Item>> perhaps work? then instead of itemMap.put("Coal", coal), you'd have to make sure that itemMap.get("Coal") already has an array list, and append the new item to the list.
Did you know you could specify your map with statements like these:
HashMap<Integer, Item[]> map = new HashMap<Integer, Item[]>();
or
HashMap<String, Item[]> map = new HashMap<String, Item[]>();
Associating each set/array/list of items with an integer or string could work for your problem.
If I'm understanding this correctly, you should have a list of all the items inside each of the HashMap to access multiple items under an item type. To do this just make a HashMap<String, ArrayList<Item>>. When you first create an item type, create a new ArrayList<Item> and on adding subsequent items of the same item type, just append to the list.
However, HashMap isn't quite that efficient for this. If you have a known quantity of item types, I would make it an ArrayList<ArrayList<Item>> such that you initialize the outer ArrayList with an initialCapacity equal to the number of item types you have and have a method that converts the name of the item type to the index that it is stored in the outer ArrayList to be more memory efficient due to lack of load factor and bypasses the overhead of the hashing function. An alternative to the method that converts name of item to index is to maybe add an item type id to each item type.
So you would have:
class Coal {
public int id = 0
}
Assuming your outer ArrayList is named itemTypes and your item is coal, adding would simply be:
itemTypes.get(coal.id).add(coal)
Your call on which implementation you want to use, the HashMap wrote is simpler and less code to write with the trade-off of less performance and increased memory use.
I have a function that returns a list like this:-
List <Column <String1, String2>>
Next I want to pass this list to a 2nd function, but
2nd function just needs a list which contains only 1st part (string1) of the Column(s) of the above list.
So I want pass just this list to 2nd function:-
List <String1>
my use case: Both the functions are from a library that I use to access database(Cassandra) for a web application. 1st function gives me a list of all columns which has two parts name(String1) and value(String2). So 1st function gives me a list of all columns(each of which has two strings) then I just need to use the list of column names to supply it to 2nd function that'll query the DB for those columns.
Since I need to do this job atleast 2-3 times before asking for data from DB for a single page, I need a superfast and a reasonably efficient method to do so.
It depends on what you mean by "efficient" (memory, execution time, something else?) and what that second function is doing.
If you care about speed and the second function is going to be looking at the items in the list repeatedly, then you should probably just copy the strings into a new List<String>:
List<String> strings = new ArrayList<String>(input.size());
for (Column<String, String> column : input) {
strings.add(column.name());
}
return strings;
If, on the other hand, the second function is going to only look at a small subset of the items or if you care more about memory than speed then you probably want a lazy view that converts items as they are accessed. Lists.transform from Google Guava can do this for you:
return Lists.transform(input, new Function<Column<String, String>, String>() {
public String apply(Column<String, String> column) {
return column.name();
}
};
Note that you may want to create he Function as a separate static class unless you're ok with it holding onto a reference to your enclosing instance. I used an anonymous class here for brevity/clarity.
I believe there is no simpler way than simply walking over the first list and ask each Column for its String1 and then add that value to your List<String1>.
If you want to separate the walking and the adding, then consider writing an Iterator which returns all the String1's from the first list, and then use traverse that.
In Scala, you could just do:
stringsList = columnsList.map(_.string2)