Joe
Joe

Reputation: 326

Java 8 Streams find element and add it to the start of the new List

I am wondering if this is possible to solve this problem with one line using Java Streams : i need to find a String in a list of strings and create another list where the search string (if found) will be the first string on the new List and then the rest of the String values

For Eg:

List<String> oldList = Arrays.asList("Avacado", "Apple", "Orange", "Chocolate");

So now if if search using say a filter "Chocolate" its should return a new list which will contain the elements in order "Chocolate", "Avacado", "Apple", "Orange".

List<String> newList =  oldList.stream().filter(i -> i.equals("Chocolate")).collect(Collectors.toList()) ???

Upvotes: 4

Views: 3841

Answers (4)

LuCio
LuCio

Reputation: 5173

You're asking for a solution using Stream. This is one:

    List<String> sorted = oldList.stream()
            .sorted(Comparator.comparing("Chocolate"::equals).reversed())
            .collect(Collectors.toList());
    System.out.println(sorted);

And it gives:

[Chocolate, Avacado, Apple, Orange]

So only "Chocolate" was moved at first index.

But actually yon don't need a Stream. The list itself is enough:

oldList.sort(Comparator.comparing("Chocolate"::equals).reversed());
System.out.println(oldList);

The result is

[Chocolate, Avacado, Apple, Orange]

... the same.

EDIT:
I've updated my answer as @Holger pointed out that it violated the contract of Comparator.compare(o1,o2). I'm using the solution Holger suggested in his comment. So he should be upvoted as I struggled two times to get a correct solution.

This approach maps each string to a boolean value which states whether the string is equal to "Chocolate". In case of equality Boolean.compare(x,y) will return 1 for x and -1 for y if the other string is not equal to "Chocolate". If x and y are equal to "Chocolate" the result is 0.
As we want to move "Chocolate" to the first index it's index has to decrease. Thus a reveresed comparator (1 => -1 and -1 => 1) is needed.

Upvotes: 4

Timothy Truckle
Timothy Truckle

Reputation: 15622

Your requerement is basically about sorting the list so you might use the sort method:

List<String> newList =  
    oldList.stream()
           .sorted((i1,i2) -> i1.equals("Chocolate")?
                           -1: // untested, so may be the other way around...
                           i2.equals("Chocolate")?
                             1:
                             i1.compareTo(i2))
           .collect(Collectors.toList())

[edit:] Thanks to @Holger we can somplify to:

List<String> newList =  
    oldList.stream()
           .sorted(Comparator.comparing("Chocolate"::equals).reversed())
           .collect(Collectors.toList())

Upvotes: 2

GolamMazid Sajib
GolamMazid Sajib

Reputation: 9437

You can do it after collecting list without targetElement and then add first postion of new list.

List<String> newList =  oldList.stream().filter(i -> !i.equals("Chocolate")).collect(Collectors.toList());
    if(oldList.size() != newList.size()){
        newList.add(0,"Chocolate");
    }

Upvotes: 1

Sweeper
Sweeper

Reputation: 270995

I personally don't think that Streams are suitable for this task. A procedural way to do this is more readable in my mind.

Here's my solution. The commented code is the procedural way of doing so. I used integers for convenience but strings are the same.

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
//        int index = list.indexOf(3);
//        ArrayList<Integer> resultList = new ArrayList<>();
//        resultList.add(list.get(index));
//        resultList.addAll(list.subList(0, index));
//        resultList.addAll(list.subList(index + 1, list.size()));
        List<Integer> resultList = Stream.concat(Stream.of(3), list.stream().filter(x -> x == 3)).collect(Collectors.toList());
        System.out.println(resultList);

Upvotes: 0

Related Questions