List of lists and Java 8 - java-8

I have a list of class R with list of other class P
List<R> rList = getRListFromDb();
I would like to get the all the P objects in another list
List<P> result = new ArrayList<>();
I tried these, but giving me Class cast exception, saying class P cannot be converted to class R. By the way I have seen issue given below, but tried and could not figure it out.
How can I turn a List of Lists into a List in Java 8?
1. rList.stream().map(R::getP).flatMap(List::stream).forEach(result::addAll);
2. rList.forEach(r -> result.addAll(r.getP()));
I would like to what is incorrect here and also would like to know different ways of getting this done in Java 8.

rList.stream().map(R::getP).flatMap(List::stream).forEach(result::addAll);
would work if you didn't use flatMap (since addAll requires a Collection, but flatMap transforms your Stream<List<P>> to a Stream<P>.
This would work:
rList.stream().map(R::getP).forEach(result::addAll);
With flatMap it should be:
rList.stream().map(R::getP).flatMap(List::stream).forEach(result::add);
That said, the correct way is to use collect:
List<P> result = rList.stream()
.map(R::getP)
.flatMap(List::stream)
.collect(Collectors.toList());
or
List<P> result = rList.stream()
.flatMap(r -> r.getP().stream())
.collect(Collectors.toList());

Related

Using Optionals and forEach in Java 8, check for empty object

I would like to use Optionals with forEach in my example below, and am not sure about the correct approach.
Basically the functionality is as follows:
List<Long> myList;
List<Long> myResultList;
myList = getValues_A();
if (null != myList && !myList.isEmpty())
return;
for (Long singleVal : myList) {
List<Long> tempList = getValues_B(singleVal);
if (null != tempList && !tempList.isEmpty())
myResultList.addAll(tempList);
}
So I simple retrieve some data into myList, check if there is some value returned, and if so, I use the result to again retrieve data and put it in a final result list.
My idea with Optionals:
List<Long> myList;
List<Long> myResultList;
myList = getValues_A();
if (null != myList && !myList.isEmpty())
return;
myResult.forEach(itemToCheck -> Optional
.ofNullable(getValues_B(itemToCheck))
.ifPresent(myResultList::addAll));
Questions:
The first part:
myList = getValues_A();
if (null != myList && !myList.isEmpty())
return;
Is there any way to use Java 8 Optionals instead?
I.e.
myList = getValues_A();
if (!Optional.ofNullable(myList).isPresent())
return;
But this would only check for null and not if the object was empty (for which I also want to return). Can this be extended with a size check of the object within the Stream?
Also, misusing Optional's isPresent as a nullcheck only is bad coding practise I guess. Any other ideas?
The second part:
I assume that even empty objects will be attempted to be added to myResultList? Can this be somehow prevented in a similar approach, i.e. check if size = 0 within the stream?
myResult.forEach(itemToCheck -> Optional
.ofNullable(getValues_B(itemToCheck))
.ifPresent(myResultList::addAll));
Small sidenote: I can't use isEmpty(Object object) of org.apache.commons.lang3.ObjectUtils as I'm with version < 3.9.
I also think it is worth mentioning that besides whole reusing Optional is not good thing in any possible case(with which I agree). We also see in this approach that we create empty list and then altering its state by adding new elements. I thing if we can we should always avoid such solutions. Much cleaner approach is to instantiate list with its elements while declaring.
For getting rid of first part, you can make the getValues_A() function to return an Optional or an empty list instead of null.It make no sense to make any processing with Optional in this method.
Second part written with stream :
List<Long> myResultList = myList.stream().map(singleVal -> getValues_B(singleVal)).filter(Objects::nonNull).flatMap(List::stream).collect(Collectors.toList());
Each steps explained:
1. map(singleVal -> getValues_B(singleVal)) - each element of the list will be processed and you'll get a List as result for each.
2. filter(Objects::nonNull) - remove empty lists
3. flatMap(List::stream) - from stream of List<Long>,you'll obtain a stream of Long
4. collect(Collectors.toList()) - collect all resultList.
You may take advantage of the orELseGet() API of the Optional and the map/flatmap APIs of the stream to simplify your code.
List<Long> resultList = Optional.ofNullable(getValues_A())
.orElseGet(Collections::emptyList)
.stream()
.filter(Objects::nonNull)
.flatMap(l -> Optional.ofNullable(getValues_B(l))
.orElseGet(Collections::emptyList)
.stream()
.filter(Objects::nonNull))
.collect(Collectors.toList());

How to return the count, while using nested foreach loops in the stream

I am using java8 streams to iterate two lists, In that one list contains some custom objects and another contains string.
With this, I have to call a method by passing custom object and sting as a input and then I have to get the count.
This is what I tried:
public int returnCode() {
/*int count = 0;
* list.forEach(x -> {
list2.forEach(p -> {
count+ = myDao.begin(conn, x.getCode(), p);
});
return count;
});*/
}
compiler is giving an error that count should be final.
Can anyone, give me how to do this in a better way.
What you're attempting to do is not possible as local variables accessed from a lambda must be final or effectively final i.e. any variable whose value does not change.
You're attempting to change the value of count in the lambda passed to the forEach hence the compilation error.
To replicate your exact code using the stream API, it would be:
int count = list.stream()
.limit(1)
.flatMapToInt(x -> list2.stream().mapToInt(p -> myDao.begin(conn, x.getCode(), p)))
.sum();
However, if you want to iterate over the entire sequence in list and not just the first then you can proceed with the following:
int count = list.stream()
.flatMapToInt(x -> list2.stream().mapToInt(p -> myDao.begin(conn, x.getCode(), p)))
.sum();
Lambdas mainly substitutes anonymous inner classes. Inside an anonymous inner class you can access only final local variables. Hence the same holds true with lambda expressions. Local variable is copied when JVM creates a lambda instance, hence it is counter intuitive to allow any update to them. So declaring the variable as final would solve the issue. But if you make it final you won't be able to do this, leading to another pitfall.
count+ = myDao.begin(conn, x.getCode(), p);
So your solution is not good and does not comply with lambda. So this will be a one way of doing it.
final int count = customObjects.stream()
.mapToInt(co -> strings.stream().mapToInt(s -> myDao.begin(conn, co.getCode(), s)).sum())
.sum();

How to convert List<List<Double>> to List<Double[]> and to List<double[]> with Java 8 stream API?

I got stuck with this problem.
I've found similar answers here, but none of those solves the problem.
Should I use mapToDouble() here? Is there anything like "mapToDoubleArray"?
To convert a List<List<Double>> into a List<double[]>, you need to map each inner list into a double array using mapToDouble combined with toArray() (which is the "mapToDoubleArray" operation you are looking for).
List<double[]> res =
myList.stream()
.map(l -> l.stream().mapToDouble(d -> d).toArray())
.collect(toList());
If you want a List<Double[]> instead, you can simply use .map(list -> list.toArray(new Double[list.size()])).

Kotlin Instantiate Immutable List

I've started using Kotlin as a substitute for java and quite like it. However, I've been unable to find a solution to this without jumping back into java-land:
I have an Iterable<SomeObject> and need to convert it to a list so I can iterate through it more than once. This is an obvious application of an immutable list, as all I need to do is read it several times. How do I actually put that data in the list at the beginning though? (I know it's an interface, but I've been unable to find an implementation of it in documentation)
Possible (if unsatisfactory) solutions:
val valueList = arrayListOf(values)
// iterate through valuelist
or
fun copyIterableToList(values: Iterable<SomeObject>) : List<SomeObject> {
var outList = ArrayList<SomeObject>()
for (value in values) {
outList.add(value)
}
return outList
}
Unless I'm misunderstanding, these end up with MutableLists, which works but feels like a workaround. Is there a similar immutableListOf(Iterable<SomeObject>) method that will instantiate an immutable list object?
In Kotlin, List<T> is a read-only list interface, it has no functions for changing the content, unlike MutableList<T>.
In general, List<T> implementation may be a mutable list (e.g. ArrayList<T>), but if you pass it as a List<T>, no mutating functions will be exposed without casting. Such a list reference is called read-only, stating that the list is not meant to be changed. This is immutability through interfaces which was chosen as the approach to immutability for Kotlin stdlib.
Closer to the question, toList() extension function for Iterable<T> in stdlib will fit: it returns read-only List<T>.
Example:
val iterable: Iterable<Int> = listOf(1, 2, 3)
val list: List<Int> = iterable.toList()

LINQ from SortedList C#

I'm fairly new to C#, and completely new to LINQ.
I have an existing object of type SortedList, which I would like to filter through using LINQ. However I appear to be having issues with this, apparently as the SortedList type is not generic.
For the timebeing I've looped through the entire SortedList and manually added the objects within to a List and used LINQ to filter from there. However, that seems to me, well, rubbish.
Is there a better way to convert my SortedList to List<> (I'm not bothered about preserving the key)? Or indeed to convert my SortedList to SortedList<> perhaps?
Original SortedList class is part of Collection. Generics introduces SortedList but if you have old code, then it wont be using that.
The easiest is to use the Cast method or OfType extension method that is made available for SortedList. Those methods will give you IEnumerable list that you can apply generic Linq operations. Make sure you include using System.Linq; in the beginning then you should be able to do like below:
sortedList.Cast<int>().Where(i=>i > 5);
sortedList.OfType<Car>().Where(c=> c.Color == Color.Blue);
If you don't need to filter by Keys, just cast and filter on Values
SortedList sl = new SortedList();
sl.Add("foo", "baa");
var baas = sl.Values.Cast<string>().Where(s => s == "baa");
What about
normalList = sortedList.Items;
Does that give you the list you want?
To answer the question "Is there a better way to convert my SortedList to List<> (I'm not bothered about preserving the key)?"... Here is example, with last line as the answer, resulting in list with integers 4, 1, 3, 2:
SortedList<string,int> sortedList = new SortedList<string,int>();
sortedList.Add("One", 1);
sortedList.Add("Two", 2);
sortedList.Add("Three", 3);
sortedList.Add("Four", 4);
List<int> list = sortedList.Values.ToList();

Resources