In the below posted code, I would like to know how can I iterate through a list of Optional objects?
According to the code:
OptionalsUtils.toOptional(this.getUser_3())
.flatMap(user->user.getOptUserFavoriteTvList()
.filter(list-> list.get(???) != Optional.empty())
);#
Now i want to refer to each index in the list? how can i achieve it?
code:
OptionalsUtils.toOptional(this.getUser_3())
.flatMap(user->user.getOptUserFavoriteTvList()
.filter(list-> list.get(0) != Optional.empty())
);
private User getUser_3() {
List<Optional<String>> list = new ArrayList<>(5);
list.add(Optional.of("espn"));
list.add(Optional.of("Cnn"));
list.add(Optional.empty());
list.add(Optional.of("deutsch welle"));
User user = new User();
user.setUserName("johannas");
user.setUserEmailAddres("joha90#gmail.com");
user.setUserId("2005");
user.setUserFavoritesTvList(list);
return user;
}
public Optional<List<String>> getOptUserFavoriteTvList() {
return OptionalsUtils.toOptional(this.getUserFavoriteTvList());
}
after flatMap, extract the list from the optional if present via orElse and then apply your logic...
OptionalsUtils.toOptional(this.getUser_3())
.flatMap(user-> user.getOptUserFavoriteTvList())
.orElse(Collections.emptyList());
after the call to orElse, you're now working with a List<String> which you can call stream() upon to perform more complex operations or iterate through it using a typical for loop etc...
you could even go with ifPresent if it's more suitable for the task at hand.
OptionalsUtils.toOptional(this.getUser_3())
.flatMap(user-> user.getOptUserFavoriteTvList())
.ifPresent(list -> list.forEach(e -> ....));
Related
I am displaying markers from my database on my map, But i have a filter for the user from where he can adjust the time and the markers will show in that time. I want to observe the list that is updated each time when the user changes the time filter. He selects a start time and end time and I query from the database to get a list with that condition .. I want to observe this list? How can I do that?
my ViewModel:
public MediatorLiveData<List<LocationTracking>> fetchData(LiveData<List<LocationTracking>> source){
if (oldSource == null){
oldSource = source;
} else {
list.removeSource(oldSource);
}
list.addSource(source, locationTrackings -> {
list.postValue(locationTrackings);
});
return list;
}
And in my activity I'm doing this:
My callback isn't called for on change when a new value is inserted in my database. Any help would be highly appreciated.
When the user wants to see whole list without time filter.
mViewModel.fetchData(mViewModel.getFilteredLocationList(
mDataRange.get(0).getTimeStamp(),
mDataRange.get(1).getTimeStamp()
)).observe(this,mFilteredListObserver);
When the user selects a time Filter.
mViewModel.fetchData(mViewModel.getFilteredLocationList(
data.getLongExtra(LocationsFilterActivity.START_TIME, 0),
data.getLongExtra(LocationsFilterActivity.END_TIME, 0)
)).observe(this,mFilteredListObserver);
I've struggled with a similar problem. Once you understand the solution it's quite simple. You need to do something like this in your ViewModel:
private MutableLiveData<DataRange> dataRange = new MutableLiveData<DataRange>();
public LiveData<List<LocationTracking>> list = Transformations.switchMap(dataRange,
newDataRangeValue -> getFilteredLocationList(
newDataRangeValue.get(0).getTimeStamp(),
newDataRangeValue.get(1).getTimeStamp())
);
public void onDataRangeChanged(DataRange dataRange) {
this.dataRange.setValue(dataRange);
}
In your Activity observe the list. The switchMap() method will listen for any changes on dataRange so if you do mViewModel.onDataRangeChanged(newDataRange), getFilteredLocationList() will be called again and list will be updated in Activity.
I highly recommend reading this great article.
I am not sure what exactly to use but lately, I have had a lot of trouble with RxJava when I am working with code that has streams for everything.
In my case, let say I have to get an instance of an object, that I need for some processing from a stream that is available, let's call this NeededInstance and so I have access to Observable of NeededInstance.
Next, what I am doing is I have a Single of a List of SomeObject and what I do is I need to iterate over all items and update them.
I do this in the following way:
.map(/*in this map the Single<List<SomeObject>> is created*/)
.flatMap(Single<List<SomeObject>> -> updateWithData(Single<List<SomeObject>>);
this is how I wanted my updateWithData function to look like:
private Single<List<SomeObject>> updateWithData(List<SomeObject> list) {
return
Observable.just(list)
.flatMapIterable(listItem -> listItem)
.flatMapSingle(listItem -> updateListItem(listItem))
.toList();
}
I do the above code so that I can transform a chain from handling a single list to an observable of items that I update and return to a list again. Below is the updateListItem function, where trouble comes when I try to get something from that other stream I mention in the beginning:
updateListItem(ListItem listItem) {
return
Observable<NeededInstance>.map(Optional::get)
.flatMapSingle(neededInstance -> workWithListItemAndNeededInstace(listItem, neededInstance))
.map(integer -> {
// do something with integer soming from the above method and with a listItem passed into this function
}
return Single.just(updatedListItem)
}
so, to be sure, workWithListItemAndNeededInstance can't update the listItem, I just get an Integer object there and with that, I have to do my own updating of listItem. Then I am trying to either return a Single of a listItem or listItem itself and somehow make it available for a .toList() so that in the end I still have a Single of a List of ListItem in the stream.
I am trying with combine but can't really make it work and I find RxJava a bit weird when I have streams that I need to just "drop in" and leave something that I can use for processing.
Any clarification is welcome.
//You have a list of string object
List<String> intList = new ArrayList<>();
Collections.addAll(intList, "1", "2", "3", "4", "5");
//Now what you want here is append neededInstance to each item in list and get it as a list.
//So output would be like List of (test1, test2, test3, test4, test5);
Observable
//iterate through the list of items and pass one by one to below stream
.fromIterable(intList)
//Each item from the list is passed down to workWithListItemAndNeededInstace
.flatMap(item -> workWithListItemAndNeededInstace(item))
.toList()
.subscribe();
/*
This method will combine item from list with the neededInstance and return a stream of combined data
*/
private Observable<String> workWithListItemAndNeededInstace(String item) {
return neededInstance().map(instance -> instance + item);
}
/*
This will be your stream from which you get needed stream
*/
private Observable<String> neededInstance() {
return Observable.just("Need instance");
}
Hope this solution gives you a rough idea on what you would want to achieve. Let me know if I missed anything, so that I can update this answer.
It's been a while that I just started to learn how to develop in Kotlin.
There is this thing that I am working on, I am trying to parse a list into another type of list. Basically they are the same thing but with different names. But when I try to populate the new list with the data that I get from the list given as parameter in the function the list only gets populated with the first object.
Here is my function:
fun convertRoomClass(course: List<Course>) : List<Courses> {
lateinit var list : List<Courses>
course.forEach {
val id = it.pathID
val name = it.pathName
val desc = it.pathDescription
val crs : Courses = Courses(id, name!!, desc!!)
list = listOf(crs)
}
return list
}
The error in your code is that you are making a list in every iteration of the loop. You should make the list first and then add every item from the loop to it!
fun convertRoomClass(courses: List<Course>) : List<AnotherCourseClass> {
val newList = mutableListOf<AnotherCourseClass>()
courses.forEach {
newList += AnotherCourseClass(it.pathID, it.pathName, it.pathDescription)
}
return newList
}
A better solution is to use the map function
fun convertRoomClass(courses: List<Course>) = courses.map {
AnotherCourseClass(it.pathID, it. pathName, it.pathDescription)
}
You might be looking for Kotlin Map
Example:
course.map { Courses(it.pathID, it.pathName,it.pathDescription) }
You're getting the list with only on object, cause the function listOf(crs) returns a list of all objects that are passed as a parameters. Saying the same thing in Java you're doing something like this:
for (course: Courses) {
Course course = new Course(...);
List<Course> list = new ArrayList<>();
list.add(course);
return list;
}
As you can see the it created new list with a single object per iteration.
What you're trying to achieve, can be done with operator map{...} which simply transforms every object in the initial list using code passed inside map and returns list of transformed objects
course.map{ Courses(...) }
Also, I've noticed that you're using the !! operator when creating a Courses object. Probably because the Course can have nullable name, while Courses can't. I'm considering this as a bad practice, cause in this case you're saying
Please throw an Exception if the name is null.
I think that a much better approach is to provide an alternative, like:
val name = course.name ?: "default", saying
Please use name or "default" if the name is null.
or skip objects without name, or any other approach that suits your situation.
You could use MutableList instead of List. That enable you to append new element at the end of your list instead of replace the entire list by doing : list = listOf(crs)
So replace the type of your var lateinit var list : List<Courses> by lateinit var list : MutableList<Courses> then replace list = listOf(crs) by list.add(crs)
Hope it helps and have fun :)
I have the following code in my activity where I am trying to fetch data from realm and then display it in a list. I have used a listener which works perfectly.
private RealmResults<Data> mData = repo.fetchData();
// internally the call is handled by
realm.where(Data.class).findAllAsync();
mData.addChangeListener(data -> {
// access to the data stored locally
// receive updates in case data changes
// set the data to the list
});
At a later point in the app, I want to also be able to filter the above data based on a user entered search string and receive the results in the same listener. I have tried the following code.
mData = poiRepo.fetchData("query");
That doesn't seem to work, I'm guessing because it returns a new list to which the listener is not attached. Is there a way I can listen for changes in the result of a realm query when the underlying data has not changed or any other way?
What I am trying to achieve.
mData.addChangeListener(data -> {
// single place where filtered data is delivered and sent to recycler view
});
function a(){
repo.fetchData( //filter parameters )
}
function b(){
repo.fetchData( //filter parameters )
}
function c(){
repo.fetchData( //filter parameters )
}
I am working in a translator kind of app and i need some help.
I have a class with getters and setters for my Array List objects. Each object has a phrase, a meaning, and usage.
so i have this to create my list:
ArrayList<PhraseCollection> IdiomsList = new ArrayList<PhraseCollection>();
now how do i add these objects to the list, each object containing the phrase, its meaning, and a use in a sentence?
For Example: The Layout would be something like this
Phrase
Kick the bucket
Meaning
When someone dies
Usage
My grandfather kicked the bucket
Thanks a lot
this is what i came up with that worked for me
private void loadIdioms() {
//creating new items in the list
Idiom i1 = new Idiom();
i1.setPhrase("Kick the bucket");
i1.setMeaning("When someone dies");
i1.setUsage("My old dog kicked the bucket");
idiomsList.add(i1);
}
ArrayList has a method call add() or add(ELEMENT,INDEX);
In order to add your objects you must first create them
PhraseCollection collection=new PhraseCollection();
then create the ArrayList by
ArrayList<PhraseCollection> list=new ArrayList<PhraseCollection>();
add them by :
list.add(collection);
Last if you want to render that in your ListView item, you must override the toString() in your PhraseCollection.
I suppose you would use the add(E) method (http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html#add(E)).
Here is an example using your example provided.
public class Phrase {
public final String phrase, meaning, usage;
//TODO: implement getters?
public Phrase(String phrase, meaning, usage) {
this.phrase = phrase;
this.meaning = meaning;
this.usage = usage;
}
}
and use it like this:
// create the list
ArrayList<Phrase> idiomsList = new ArrayList<Phrase>();
// create the phrase to add
Phrase kick = new Phrase("kick the bucket", "When someone dies", "My grandfather kicked the bucket");
// add the phrase to the list
idiomsList.add(kick);