Java流映射列表,用于设置和保留订单

时间:2018-03-02 12:45:44

标签: java java-stream

我有答案课程和用户课程。

答案有getUser(),用户有getPoints()

从答案列表中我想得到一个按点排序的用户哈希集。我试过以下:

 Set<User> collectSet = list.stream().map(Answer::getUser)
            .sorted(Comparator.comparing(User::getPoints))
            .collect(Collectors.toCollection(HashSet::new));

 collectSet.forEach(a -> System.out.println(a.toString()));

不幸的是,这似乎并未保留订单。输出总是不同的。

有趣的是,列表的相同示例可以正常工作

List<User> collectList = list.stream().map(Answer::getUser)
            .sorted(Comparator.comparing(User::getPoints))
            .collect(Collectors.toList());

collectList.forEach(a -> System.out.println(a.toString()));

我做错了什么?

3 个答案:

答案 0 :(得分:5)

Debug.Print "Attribute Text: ", Attribute.Text

首先,您要根据某些 Collectors.toCollection(LinkedHashSet::new) 对这些条目进行排序 - 给予他们&#34;一些&#34;顺序,但然后你把它们放入Comparator(订单被破坏),因此结果不同。使用HashSet收集它们以保留排序顺序。

如果您仍想将它们收集到LinkedHashSet,您可以:

List

操作本身的顺序( yourList.stream() .sorted(....) .distinct() .collect(Collectors.toList()) vs distinctmatters

答案 1 :(得分:3)

HashSet不会保留插入顺序,但List会保留。您可以尝试使用LinkedHashSet

修改 另一种方法是使用TreeSet。它是一个集合,因此删除了重复的值。并且元素在插入时进行排序。使用方法compareTo(由Comparable接口提供)进行排序。 例如:

// Answer class
public class Answer {

    private final User user;

    public Answer(final User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }
}

// User class
public class User implements Comparable<User> {

    private final int points;

    public User(final int points) {
        this.points = points;
    }

    public int getPoints() {
        return points;
    }

    @Override
    public int compareTo(User other) {
        // Sort user by their points (ascending order)
        return points - other.points;
    }

    @Override
    public String toString() {
        return "User{" + "points=" + points + '}';
    }
}

然后在你的主要代码中:

// Main
List<Answer> answers = Arrays.asList(
    new Answer(new User(0)),
    new Answer(new User(20)),
    new Answer(new User(1)),
    new Answer(new User(20)),
    new Answer(new User(10))
);

answers
    .stream()
    .map(Answer::getUser)
    .collect(Collectors.toCollection(TreeSet::new))
    .forEach(System.out::println);

输出:

User{points=0}
User{points=1}
User{points=10}
User{points=20}

答案 2 :(得分:1)

您可能想要使用TreeSet

两个用户相同没有。点数不相等,因此用户应该有一些uniqueId

我将其视为userId

此处不需要hashCodeequals(但很高兴见documentation),因为TreeSet使用Comparator(或User类可以实现Comparable)来确定两个元素是否相等。

TreeSet<User> users = answers.stream()
    .map(Answer::getUser)
    .collect(Collectors.toCollection(() -> new TreeSet<User>(
       Comparator.comparingInt(User::getPoints).thenComparing(User::getUserId))));