代码之家  ›  专栏  ›  技术社区  ›  Zombies

Java集合:如何将排序的列表划分为子列表

  •  4
  • Zombies  · 技术社区  · 14 年前

    LinkedList<SomeObject> 包含按特定属性排序的元素(例如: SomeObject.someValue() ). 此属性可以而且通常确实经常重复/它不是唯一的,但从不为空。

    有没有一种方便的方法将其分成多个列表,每个列表只包含其基数相等的列表?另外,这可以只用一次列表迭代来完成吗?例如,原始列表:

    1, 1, 1, 2, 2, 3, 3, 3
    

    所需列表:

    1, 1, 1
    2, 2,
    3, 3, 3
    
    6 回复  |  直到 14 年前
        1
  •  10
  •   Bozho    14 年前

    不太方便,但是:

    • 开始循环。存储上一个项目,并将其与当前项目进行比较。
    • 如果前一个与当前不同(使用 equals(..) ,小心 null List ,或使用 list.subList(groupStart, currentIdx)
        2
  •  4
  •   crunchdog    14 年前

    Apache CollectionUtils 为此,其中“list”是原始列表,“value”是要为其提取子列表的对象的当前值:

    Collection<SomeObject> selectedObjects = CollectionUtils
        .select(list,
                new Predicate() {
                    boolean evaluate(Object input) {
                        return ((SomeObject) input).someValue().equals(value);    
                    }
                });
    

    这种方法意味着使用一个众所周知的、经过良好测试的库(这总是一件好事),但缺点是,对于您需要的每个子列表,您将循环遍历该列表一次。

        3
  •  3
  •   shoebox639    14 年前

    很肯定没有一个java API方法来实现这一点。但是你可以写:

     // This assumes your list is sorted according to someValue()
     // SomeValueType is the type of SomeObject.someValue()
     public Map<SomeValueType, List<SomeObject>> partition(List<SomeObject> list) {
        Object currValue = null;
        HashMap<SomeValueType, LinkedList<SomeObject>> result = new HashMap<SomeValueType, LinkedList<SomeObject>>();
        LinkedList<SomeObject> currList = null;
    
        for (SomeObject obj : list) {
            if (!obj.someValue().equals(currValue()) {
                currValue = obj.someValue();
                currList = new LinkedList<SomeObject>();
                result.put(currValue, currList);
            }
            currList.add(obj);
        }
    }
    

    这会给你一个 HashMap 子列表,其中键是 someValue

    编辑:使此返回hashmap而不是arraylist。

        4
  •  3
  •   Margus    14 年前

    如果你想用谷歌 Guava-libaries

    import com.google.common.collect.HashMultiset;
    import com.google.common.collect.Lists;
    
    public class Example {
        public static void main(String[] args) {
            HashMultiset<Integer> ints = HashMultiset.create();
            ints.addAll(Lists.newArrayList(1, 1, 1, 2, 2, 3, 3, 3));
            System.out.println(ints);
        }
    }
    

    输出:

    [1 x 3, 2 x 2, 3 x 3]
    

    如果你需要计算x有多少元素 ints.count(x);

        6
  •  1
  •   Reese Moore    14 年前

    这应该有效(未经测试,但我确信一切正常,这也假设列表的内容是可排序的):

    public static List[] getEquivalentSubLists( List parent )
    {
    
        List cloneList = parent.clone();
        Collections.sort(cloneList);
    
        ArrayList<List> returnLists;
        int end;
        while (cloneList.size() > 0)
        {
            end = cloneList.lastIndexOf(cloneList.get(0));
    
            returnLists.add(cloneList.subList(0, end));
            cloneList.removeAll(cloneList.subList(0, end));
        }
    
        return returnList.toArray();
    }