Java 8 - 按属性定义的对象集合,其中包含在数组中定义的顺序

时间:2016-12-27 10:43:28

标签: sorting java-8 java-stream

假设我有以下课程:

public class Foo {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public Foo setId(int id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

    public Foo setName(String name) {
        this.name = name;
        return this;
    }
}

然后,我在Foo中有几个Collection<Foo> fooCollection个对象和字符串数组String[] names

现在,我想按属性fooCollection订购namename中订购names字符串的顺序相同。

如何使用Java 8 Stream做到这一点?

4 个答案:

答案 0 :(得分:4)

您可以使用Arrays.asList(names).indexOf(f.getName())作为比较键:

List<String> nameList = Arrays.asList(names);
List<Foo> fooList = new ArrayList<>(fooCollection);
fooList.sort(Comparator.comparingInt(f -> nameList.indexOf(f.getName())));

或者如果你一定想要Stream API:

List<Foo> fooList = fooCollection.stream()
    .sorted(Comparator.comparingInt(f -> nameList.indexOf(f.getName())))
    .collect(Collectors.toList());

但是如果你有很多名字,你可以考虑提高效率,首先准备一个反向的名字索引:

Map<String, Integer> nameMap = IntStream.range(0, names.length)
    .boxed()
    .collect(Collectors.toMap(idx -> names[idx], Function.identity()));
List<Foo> fooList = fooCollection.stream()
    .sorted(Comparator.comparing(f -> nameMap.get(f.getName())))
    .collect(Collectors.toList());

这里我假设所有名称都不同,每个Foonames数组中都有相应的名称。

答案 1 :(得分:0)

首先,您使用static factory methodsComparator数组构建names,例如通过数组上的reduction。然后将比较器传递给stream.sort

答案 2 :(得分:0)

首先,您需要将String[]转换为List<String>才能利用indexOf方法。然后使用Foo.name接口比较新名称List中Comparator<T>的等效索引。我制作了整个代码,以便您可以复制并运行它:

package io.github.gabrielbb.java.utilities;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 *
 * @author Gabriel Basilio Brito
 * @since 27-12-16
 */
public class CollectionSortingBasedOnArray {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("Donald", "Trump"));
        personList.add(new Person("Gabriel", "Basilio"));
        personList.add(new Person("Chris", "Brown"));
        personList.add(new Person("Barack", "Obama"));

        String[] sortedNames = {"Barack", "Chris", "Donald", "Gabriel"};
        List<String> sortedNamesList = Arrays.asList(sortedNames); // Converting Array to List to take advantage of "indexOf" method

        Collections.sort(personList, (Person p1, Person p2) -> { // Using the Comparator<T> interface with Lambda Expression
            Integer n1 = sortedNamesList.indexOf(p1.getName()); // Get the position of the first person name in the Names List (before an Array)
            Integer n2 = sortedNamesList.indexOf(p2.getName()); // Get the position of the second person name in the Names List
            return n1.compareTo(n2); // Now is simple: Just compare those indexes.
        });

        // Collections.sort lines can be replaced with: personList.sort(Comparator.comparingInt(p -> sortedNamesList.indexOf(p.getName())));

        personList.stream().forEach((p) -> {
            System.out.println(p.getName() + " " + p.getLastName()); // Print each Person Information
        });
    }
}

class Person {

    private String name;
    private String lastName;

    public Person(String name, String lastName) {
        this.name = name;
        this.lastName = lastName;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the lastName
     */
    public String getLastName() {
        return lastName;
    }

    /**
     * @param lastName the lastName to set
     */
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

}

Collections.sort行是为了更好地理解背后发生的事情,但它可以替换为:

personList.sort(Comparator.comparingInt(p -> sortedNamesList.indexOf(p.getName())));

答案 3 :(得分:-1)

已经有一段时间了,但你可以像这样缩短比较

List fooSortedByName = new ArrayList(fooCollection);
fooSortedByName.sort(Comparator.comparing(Foo::getName));