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

落爺英雄遲暮 提交于 2019-12-10 10:07:04

问题


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()) ???

回答1:


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.




回答2:


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())



回答3:


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");
    }



回答4:


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);


来源:https://stackoverflow.com/questions/51519499/java-8-streams-find-element-and-add-it-to-the-start-of-the-new-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!