Send index in my map function using java stream - java

I have a method that return me an List<String[]> like that:
return getElements()
.stream()
.map(Element::elements)
.collect(Collectors.toList());
My elements function look like that:
public String[] elements ()
I want to send the index of the current iteration in my elements method so i try to give an index in my map like that and to put an index arguments in my elemnts method.
return getElements()
.stream()
.map(Element::elements, index)
public String[] elements (int index)
I have the following errors:
'map(java.util.function.Function? super ch........,? extends java.lang.String[]>)' in 'java.util.stream.Stream' cannot be applied to '( , int)'
I tried to use a filter and then use mapToObj but it don't recognize the mapToObj function.
I need to send the index because i need to do a specific check in me method if the index is equal to 3.
Is it a way to filter with the index or to send the index to my map method ?
I already tried AtomicInteger:
AtomicInteger index = new AtomicInteger(0);
return getAllokationen()
.stream()
.map(Element::element, index.getAndIncrement())
.collect(Collectors.toList());
Without sucesss
Thank you

A concise solution will be to use IntStream. Your question is a bit vague on the input parameters to the elements() function, never the less, I've assumed that getElements() returns a List<Elements> and you require the index of that list to perform the operation.
List<Elements> elementList = getElements();
IntStream.range(0, elementList.size())
.mapToObj(index -> elementList.get(index).elements(index))
.collect(Collectors.toList());
Hope this works out for you.

Related

Printing max element in a Deque<Integer>

I have a Deque from Integers, which I'm using as a Que. I have to add and remove elements from it and in some cases I need to print the max value in the Que.
The thing that I've tried is:
System.out.println(deque.stream().max(Integer::compareTo));
But it prints - Optional[the current max int].
Thank you!
That is because the max method of java.util.Stream returns your value wrapped in Optional. This is the signature of the max method Optional<T> max(Comparator<? super T> comparator);
The example below would provide you the expected behaviour:
Optional<Integer> optionalOfMax = deque.stream().max(Integer::compareTo);
System.out.println(optionalOfMax.orElseThrow());
You can do it as follows:
deque.stream().max(Integer::compareTo).ifPresent(System.out::println);
Note that deque.stream().max(Integer::compareTo) returns Optional<Integer>.
Alternatively,
deque.stream().flatMapToInt(x -> IntStream.of(x)).max().ifPresent(System.out::println);
Stream#flatMapToInt returns an IntStream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.
You can just use the code you have written and extend it by .get().
The following code
public static void main(String[] args) {
// create a Deque that holds Integers
Deque<Integer> myDQ = new ArrayDeque<Integer>();
// add some of them
myDQ.add(12);
myDQ.add(13);
myDQ.add(14);
myDQ.add(15);
myDQ.add(16);
myDQ.add(20);
myDQ.add(17);
myDQ.add(18);
myDQ.add(19);
// and print
System.out.println(
myDQ.stream()
.max(Integer::compareTo) // the largest one
.get() // not as Optional but only as Integer
);
}
just prints 20.
The max-Method returns an java.util.Optional. If you just want to return a int-Value you can use the orElse-Method from java.util.Optional to return the given value or, if not present, another default.
System.out.println(deque.stream().max(Integer::compareTo).orElse(0));
You can unbox the Integer wrappers in your queue and use IntStream.max(), which returns an OptionalInt:
deque.stream().mapToInt(Integer::intValue)
.max()
.ifPresent(System.out::println);
This will do nothing if max() returns OptionalInt.empty(), which happens when the deque is empty. If you want to check for emptiness, you can do, for example:
deque.stream().mapToInt(Integer::intValue)
.max()
.ifPresentOrElse(System.out::println,
() -> throw new RuntimeException("Attempt to get max of empty collection"));

Create a sub-list according to criteria and Perform operations

I have sorted List<Pair<Integer, Integer>> and I want to create a subList for all the Pairs which having a key less than one arbitrary value k.
I want to create a subList that follows above condition and sort it.
I did something like this -
//to get the max index of the List
public static int getIndex(List<Pair<Integer,Integer>> list,int key)
{
int count=0;
for(Pair<Integer,Integer> p: list)
{
if(p.getKey()>key)
break;
count++;
}
return count;
}
Now, Sorting subList as per this criteria
int count = getIndex(current.getValue(),list);
Collections.sort(list.subList(0, count),Comparator.<Pair<Integer,Integer>>comparingInt(Pair::getValue));
Is there any elegent way to do achieve this ? I mean java 8 way.
Stream API came into my mind. But after performing operations it doesn't manipulate the underlined collection.
Something like the following.
List<Pair<Integer,Integer>> subList =
list.stream()
.filter(p->p.getKey() < key)
.collect(Collectors.toList());
This works regardless of the ordering of the pairs in the list. It constructs the new list as each pair passes thru the filter.

How to find max length in list of string using streams in Java?

I have a class like below:
public class A
{
String name;
String getName(){return name;}
}
And I also have a list like below:
List<A> list_a = new ArrayList<>();
//add n objects into list_a
Right now I would like to find the max length of object which is in list_a using streams in Java. I have created code like below:
final int max_len = list_a.stream().max(Comparator.comparingInt(A::getName::length));
But it does not work, I mean it is something bad with syntax. Could you help me with this? Thank you.
What you are using isn't lambda. Lambda looks like (arguments) -> action. What you have in A::getName is method reference, but additional ::length is not part of its syntax.
Instead of A::getName::length you can use lambda like a -> a.getName().length().
But your code has yet another problem. Code
list_a.stream()
.max(Comparator.comparingInt(A::getName::length));
is handling streams of A and max method called on Stream<A> will result in Optional<A> not int. It is Optional because there is a chance that list_a can be empty which means that there will be no valid result.
If you want to get OptionalInt you would need to map Stream<A> to Stream<String> and then map it to Stream of ints first. Then you can call its max() method and get:
OptionalInt maxOpt = list_a.stream()
.map(A::getName)
.mapToInt(String::length)
.max();
When you already have OptionalInt you can use it to check if value there isPresent() and get it via getAsInt(). You can also use orElse(defaultValueIfEmpty) like
int max = maxOpt.orElse(-1); //will return value held by maxOpt, or -1 if there is no value
You can use an IntStream as you're just looking for the max length:
OptionalInt oi = list_a.stream()
.map(A::getName)
.mapToInt(String::length)
.max()
final int max_len = oi.orElse(0); //defaulting to 0
If you need to use a custom comparator, you will need a lambda expression:
final int max_len = list_a.stream()
.max(Comparator.comparingInt(a ->
a.getName().length())) //need a lambda
.map(A::getName)
.map(String::length)
.orElse(0); //defaulting to 0
Alternative solution using Collections.max:
A a = Collections.max(list_a, Comparator.comparing(obj -> obj.getName().length()));
int maxLen = a.getName().length();
Keep in mind that Collections.max throws NoSuchElementException if the collection is empty. If you don't want it, use the approach with OptionalInt like in #Pshemo's answer.

Java - How to get item index from an array with its value?

If I have a array list say a string array, then how can I get index of an element with its value?
Code exammple:
private static final String[] TEST = new String[]{
"abc","bcd","def"
}
require its index with something like:
int i = TEST.getPosition("abc");/TEST.indexof(...);//not available
Also I tried with creating ArrayAdapter.
Is there anything like this? Or maybe I need to assign it with that adapter or something?
Or,
How can I get such index of an element?
Simplest idea:
Convert array to list and you can get position of an element.
List<String> abcd = Arrays.asList(yourArray);
int i = abcd.indexOf("abcd");
Other solution, you can iterator array:
int position = 0;
for (String obj : yourArray) {
if (obj.equals("abcd") {
return position;
}
position += 1;
}
//OR
for (int i = 0; i < yourArray.length; i++) {
if (obj.equals("abcd") {
return i;
}
}
You can refer to this question and use the Java 8 Lambda filter function.
Optional<String> optional = Arrays.stream(presents)
.filter(x -> "MyString".equals(x.getName()))
.findFirst();
if(optional.isPresent()) {//Check whether optional has element you are looking for
String s = optional.get();//get it from optional
}
the filter function take a lambda callback and will returns a list with only the values that match the condition in the lambda. In our case, we also want only the first one. That's why are add the findFirst() which will returns only the first value.
The function will returns an Optional, we can check if it contains a value using options.isPresent(). The optional.get() will returns the value.
Replace the "MyString" by your value and it should work.
If you wish to find an index, you can use the indexOf() function after changing your static array to an list : Arrays.asList(array);
There can be two methods which you can opt for -
1) First, as it is an array, you can simply run a for loop and compare using equals() and find the position.
2) Secondly, convert it into an List<> and run indexOf() and find the position.
NOTE: When you convert an array to List, it become a backed version List, it is fixed and size can't be alter --> but it is perfectly fine in your case as your array is final.
List<String> str = Arrays.asList(TEST);
int pos = str.indexOf("abc");
As others have said, the simplest method is Arrays.asList(TEST).indexOf("abc"). But here's an alternative using streams:
int index = IntStream.range(0, TEST.length)
.filter(i -> TEST[i].equals("abc"))
.findFirst()
.orElse(-1);

Java 8 filter by attribute

I have a class which is of the following definition
public class MyClass {
int val;
type t;
}
Where type is an enum with values A,B,C,D,....
I have a list of objects of MyClass and I want to filter out the first element of each type occurring in the list.
for example :-
Given list:
{{1,A},{2,A},{4,B},{5,B},{3,C}}
Output:
{{1,A},{4,B},{3,C}}
Is there a way to use filter() of a stream of the list to solve this problem?
I'm not sure if there's a way to do this with a single Stream pipeline, but you can do it with two.
The first pipeline groups the objects by the val property (producing a Map<Integer,List<MyClass>>) and the second takes the first object of each List produced by the first pipeline and collects them into the output List:
List<MyClass>
filtered = mycl.stream ()
.collect (Collectors.groupingBy (c -> c.val))
.values ()
.stream ()
.map (l -> l.get (0))
.collect (Collectors.toList ());
Here is a solution which is not as elegant I hoped for but it works:
Set<MyType> typeSet = new HashSet<>();
List<MyClass> result = list.stream()
.filter(c -> typeSet.add(c.getType())).collect(
Collectors.toList());
I'm not sure if there is any direct way of doing it but you can achieve it by doing
1) First use streams's findFirst method with filter (TypeOf type).
2) do above steps for all types.
3) Merge all above data into one list.
One of good way to achieve this override equals() and hashCode() in your MyClass class. Check equality on the basis of 'type'. Then put your List in Set it will remove all duplicate. :)

Categories

Resources