计算具有财产的物品数量

时间:2012-02-06 18:29:29

标签: java list

我有List<Custom>列表Custom就像

class Custom{
    public int id;
    public String name;
}

如何获取名称为“Tom”的项目数量?是否比for循环更简单?

10 个答案:

答案 0 :(得分:11)

现在可以使用Java 8流轻松完成 - 无需额外的库。

List<Custom> list = /*...*/;
long numMatches = list.stream()
                      .filter(c -> "Tom".equals(c.name))
                      .count();

答案 1 :(得分:5)

如果要在多个位置按名称进行过滤,特别是如果要将该过滤器与运行时确定的其他过滤器链接起来,Google Guava谓词可能会对您有所帮助:

public static Predicate<Custom> nameIs(final String name) {
    return new Predicate<Custom>() {
        @Override public boolean apply(Custom t) {
            return t.name.equals(name);
        }
    };
}

一旦编码了该谓词,过滤和计数只需要一行代码。

int size = Collections2.filter(customList, nameIs("Tom")).size();

正如您所看到的,与循环(命令式样式)相比,谓词(函数式)的冗长构造并不总是更易读,更快或者保存代码行。实际上,Guava documentation明确指出默认情况下应该使用命令式样式。但谓词无论如何都是一个很好的工具。

答案 2 :(得分:4)

就我个人而言,我喜欢使用Apache Commons Collection lib。 (但是因为它使用了泛型,所以在sourceforge上的那个)它可以让你做一些非常优雅的事情,比如映射列表或过滤列表(以方案方式)。你最终会写这样的东西:

int count = CollectionUtils.countMatches(myList, new Predicate<Custom>(){
    public boolean evaluate(Custom c){ return "Tom".equals(c.name); }
}

唯一的缺点是,由于Java没有一阶函数,你必须编写像Predicate实例这样的小对象。如果你能写匿名函数会更干净。即在斯卡拉,就是这样:

val myList = List("a", "a", "b", "c", "a")
val c = myList.count{ "a".equals(_) }  // is 3

答案 3 :(得分:2)

标准集合没有更简单的解决方案。您必须遍历列表并计算名称的出现次数。

答案 4 :(得分:1)

您可以在添加或删除列表中的项目时进行跟踪。这可以取代hashmap Name-&gt; Count。当你添加一个项目时,你增加该名称的计数,当你删除它时,你减少计数。

或者您通过循环检查有问题的名称来迭代集合。

根据应用程序的行为,其中一种方法会更快,但如果没有更多信息,则很难分辨出哪种方法。

答案 5 :(得分:1)

可能更容易。 现在,您可以将对象存储在Map&lt; String,List&lt; Custom&gt;&gt;而是密钥是名称的地方。 要获得name ==“Tom”的项目数,您可以简单地执行:

List<Custom> l = myMap.get("Tom");
int count = 0;
if (l != null) {
    count = l.size();
}

答案 6 :(得分:1)

您也可以在循环之前对列表进行排序,然后使用“分而治之”来查找匹配项,然后计算。这真的取决于你的需求,比如有多少元素?搜索后有很多插入吗?等

答案 7 :(得分:1)

现在定义它的方式总是需要在列表上循环。

使用名称映射创建辅助索引到ids列表是一个好主意。

另一个选择是确保列表按名称排序,在这种情况下,所有“Tom”将彼此相邻存储。然后你可以在O(log(n))时间内用二进制搜索找到第一个“Tom”,然后从那里继续计数,直到你到达非“Tom”或列表的末尾。插入操作将具有O(n)复杂度,因为您需要将插入位置之后的所有元素移动一个位置,因此请仔细考虑: - )

答案 8 :(得分:0)

这个怎么样? :

package test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class CustomArrayBuilder extends ArrayList<Custom> {

    Map<String, Integer> namesMap = new HashMap<String, Integer>();

    public CustomArrayBuilder(Collection<? extends Custom> c) {
        super(c);
        this.prepareAddAll(c);
    }

    public int getDifferentNamesAmount() {
        return this.namesMap.size();
    }

    public int getNameAmount(String name) {
        Integer integer = this.namesMap.get(name);
        return (integer != null) ? integer : 0;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Custom set(int index, Custom element) {
        Custom custom = super.set(index, element);
        prepareSet(custom, element);
        return custom;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean add(Custom e) {
        this.prepareAdd(e);
        return super.add(e);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void add(int index, Custom element) {
        this.prepareAdd(element);
        super.add(index, element);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Custom remove(int index) {
        Custom custom = super.remove(index);
        this.prepareRemove(custom);
        return custom;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void clear() {
        super.clear();
        this.namesMap.clear();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean addAll(Collection<? extends Custom> c) {
        this.prepareAddAll(c);
        return super.addAll(c);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean addAll(int index, Collection<? extends Custom> c) {
        this.prepareAddAll(c);
        return super.addAll(index, c);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean remove(Object o) {
        if (super.remove(o)) {
            this.prepareRemove((Custom) o);
            return true;
        } else {
            return false;
        }
    }

    private void prepareSet(Custom oldCustom, Custom newCustom) {
        if (oldCustom != null && !oldCustom.name.equals(newCustom.name)) {
            this.prepareRemove(oldCustom);
            this.prepareAdd(newCustom);
        }
    }

    private void prepareAdd(Custom custom) {
        if (custom != null) {
            Integer integer = this.namesMap.get(custom.name);
            this.namesMap.put(custom.name, (integer != null) ? integer + 1 : 1);
        }
    }

    private void prepareAddAll(Collection<? extends Custom> c) {
        for (Custom custom : c) {
            this.prepareAdd(custom);
        }
    }

    private void prepareRemove(Custom custom) {
        if (custom != null) {
            Integer integer = this.namesMap.get(custom.name);
            this.namesMap.put(custom.name, (integer != null && integer > 0) ? integer - 1 : 0);
        }
    }
}

<强>用法:

package test;

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {

        List<Custom> list = new ArrayList<Custom>() {{
            add(new Custom("A"));
            add(new Custom("B"));
            add(new Custom("C"));
            add(new Custom("A"));
            add(new Custom("A"));
            add(new Custom("B"));
        }};

        CustomArrayBuilder customs = new CustomArrayBuilder(list);
        Custom custom = new Custom("B");
        customs.add(custom);
        customs.add(custom);
        customs.remove(custom);
        customs.remove(custom);
        customs.remove(custom);

        System.out.println("A: " + customs.getNameAmount("A"));
        System.out.println("B: " + customs.getNameAmount("B"));
        System.out.println("C: " + customs.getNameAmount("C"));
        System.out.println("Z: " + customs.getNameAmount("Z"));
        System.out.println("Total different names: " + customs.getDifferentNamesAmount());
    }
}

<强>输出:

A: 3
B: 2
C: 1
Z: 0
Total different names: 3

当您经常使用计数操作时,它可能很有用。 注意:您不应该更改自定义对象的名称,它应该是最终的:

package test;

class Custom {
    public int id;
    final public String name;

    public Custom(String name) {
        this.name = name;
    }
}

或者,当您从列表中更改某个Custom对象的名称时,您也必须对列表执行某些操作。

答案 9 :(得分:0)

您可以使用Eclipse Collections中的count()

MutableList<Custom> customList = Lists.mutable.empty();
int count = customList.count(each -> "Tom".equals(each.getName()));

如果您无法从List更改customList:

List<Custom> customList = new ArrayList<>();
int count = ListAdapter.adapt(customList).count(each -> "Tom".equals(each.getName()));

如果您有检查名称的方法,也可以使用countWith()

MutableList<Custom> customList = Lists.mutable.empty();
int count = customList.countWith(Custom::isNamed, "Tom");

class Custom
{
    public int id;
    public String name;

    public boolean isNamed(String nameToCheck)
    {
        return nameToCheck.equals(this.name);
    }
}

注意:我是Eclipse Collections的撰稿人。

相关问题