根据属性对不同列表中的对象进行分类

Posted

技术标签:

【中文标题】根据属性对不同列表中的对象进行分类【英文标题】:Categorize objects in different lists depending on a property 【发布时间】:2018-05-23 12:58:34 【问题描述】:

我在使用 interest 属性对不同列表中的对象进行分类时遇到问题。

我有一个用户对象列表作为列表,我的用户类如下所示:

class User 
    private int id;
    private String name;
    private String interest;
    //constructors, getters & setters etc...

我正在尝试根据某种兴趣来显示用户,但我觉得除了我尝试过的方法之外,还有一种更简单的方法。

除了在switch 中使用一组固定的元素之外,我还需要动态的兴趣列表,而且我不知道是否有更好更有效的方法而不必使用 3 lists每个兴趣的列表。

这是我到目前为止所做的:

List<User> javaInterestList;
List<User> javascriptInterestList;
List<User> cInterestList;

public void category(List<User> unfilteredList) 
    for (User u : unfilteredList) 
        String interest = u.getInterest().toLowerCase();
        switch (interest) 
        case "java":
            javaInterestList.add(u);
            break;
        case "c":
            cInterestList.add(u);
            break;
        case "javascript":
            javascriptInterestList.add(u);
            break;
        
    

上面的问题,我仅限于3个兴趣,有什么办法可以解决这个问题以及更好,更清洁的方法吗?

【问题讨论】:

使用Map&lt;String, List&lt;User&gt;&gt;。使用流:Map&lt;String, List&lt;User&gt;&gt; usersByInterest = users.stream().collect(Collectors.groupingBy(User::getInterest)) 【参考方案1】:

这里要考虑的不是过滤机制,而是使用的data-structure

在这种情况下,您正在分配具有一定兴趣的不同类型的users (key)。这是地图的完美用例。

我认为您只需要在以下情况下使用地图即可。

上面的问题,我只限于3个兴趣,有什么办法可以解决这个问题

当然你可以根据自己的喜好对兴趣进行分类,看看下面的方法:

public static Map<String,List<User>> category(List<User> unfilteredList)
        Map<String,List<User>> result = new HashMap<>();
        for(User u :unfilteredList)
            String inerest = u.getInterest();
            if(result.containsKey(u.getInterest()))
                List<User> users = new ArrayList<>(result.get(inerest));
                users.add(u);
                result.put(inerest, users);
            else
                List<User> users = new ArrayList<>();
                users.add(u);
                result.put(inerest, users);
            
        
        return result;
    

有没有更好、更清洁的方法?

是的,使用Java 8 Streams,您只需一行代码即可轻松重写上述内容:

public static  Map<String,List<User>> category(List<User> unfilteredList)
        return unfilteredList.stream().collect(Collectors.groupingBy(u -> u.getInterest()));
    

【讨论】:

演员 ((User)u) 是多余的,您需要按 u.getInterest().toLowerCase() 而不是 u.getInterest() 分组,因为这正是 OP 想要的。【参考方案2】:

这是使用groupingBy 收集器的绝佳机会。

Map<String, List<User>> resultSet = 
           unfilteredList.stream().collect(
                  Collectors.groupingBy(u -> u.getInterest().toLowerCase());

现在您可以通过以下方式检索给定密钥的用户列表:

List<User> java = resultSet.get("java");
List<User> c = resultSet.get("c");
List<User> javascript = resultSet.get("javascript");

【讨论】:

以上是关于根据属性对不同列表中的对象进行分类的主要内容,如果未能解决你的问题,请参考以下文章

Python入门题045:根据对象属性进行排序

Python中元祖对象排序

根据对象中的变量对对象的数组列表进行排序

使用 lambda 根据列表的 Id 对列表中的对象进行分组

如何根据 Aurelia/Typescript 中的嵌套属性对对象数组进行排序

深入理解JavaScript中的属性和特性