从Collection中对象的字段中获取Distinct和count值

时间:2015-06-22 12:57:24

标签: java design-patterns collections guava

我有ListPin个对象(List<Pin>),其中Pin类具有以下属性:

String pinNumber, String pinType, Date insertDate

我希望得到一个HashMap <String pinNumber, int count>,其中包含不同的pinNumber,告诉我List<Pin>中有多少个不同的pinNumber以及每个pinNumber的数量。

所以我知道这样做的方法是:

  • 遍历List<Pin>
  • 检查HashMap是否已包含pinNumber的键值,并且:
  • 增加或添加(如果不存在)。

我想对Pin对象中的每个字段执行相同的操作。

我相信应该有更简单的方法吗?

也许番石榴有更简单的东西?

4 个答案:

答案 0 :(得分:3)

如果您有可能使用Java 8(并且因为您想要做的事情基本上听起来像是“分组依据”操作),这可以使用新的Stream API以优雅的方式解决(如用户vallismortis所示) ):

highest_start_date_to_be_found_of_this_element

输出:

import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        List<Pin> pins = Arrays.asList(
                new Pin("PIN-1", "T1", new Date()),
                new Pin("PIN-1", "T2", new Date()),
                new Pin("PIN-1", "T3", new Date()),
                new Pin("PIN-2", "T2", new Date()),
                new Pin("PIN-2", "T2", new Date()),
                new Pin("PIN-3", "T2", new Date())

        );
        Map<String, Long> map = pins.stream().collect(groupingBy(Pin::getPinNumber, counting()));
        System.out.println("map = " + map);
    }
}

class Pin {
    String pinNumber;
    String pinType;
    Date insertDate;

    public Pin(String pinNumber, String pinType, Date insertDate) {
        this.pinNumber = pinNumber;
        this.pinType = pinType;
        this.insertDate = insertDate;
    }

    public String getPinNumber() {
        return pinNumber;
    }

    public String getPinType() {
        return pinType;
    }

    public Date getInsertDate() {
        return insertDate;
    }
}

答案 1 :(得分:1)

你不需要番石榴。您可以使用标准Java 8功能。一种方法是使用流,但如果您需要计算多个字段的计数,则它们不适合。相反,您可以使用Map.merge方法:

Map<String, Integer> byNumber = new HashMap<>();
Map<String, Integer> byType = new HashMap<>();
Map<Date, Integer> byInsertDate = new HashMap<>();

listOfPins.forEach(pin -> {
        byNumber.merge(pin.getPinNumber(), 1, Integer::sum);
        byType.merge(pin.getPinType(), 1, Integer::sum);
        byInsertDate.merge(pin.getInsertDate(), 1, Integer::sum);
    });

这样做的好处是它只能在listOfPins上的一次迭代中完成,而对于流,你需要为每个字段一次传递。

答案 2 :(得分:0)

更简单的实施:

public static void main(String[] args) {

    List<Pin> pinList = new ArrayList<Pin>();

    // Add employee to list
    pinList.add(new Pin("1234", "local", null));
    pinList.add(new Pin("2345", "extra", null));
    pinList.add(new Pin("3456", "extra", null));
    pinList.add(new Pin("1234", "local", null));

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

    for (Pin pin : pinList) {
        Integer cnt = mapPinNumber.get(pin.getPinNumber());
        mapPinNumber.put(pin.getPinNumber(), (cnt == null) ? 1 : ++cnt);
    }
    printMap(mapPinNumber);

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

    for (Pin pin : pinList) {
        Integer cnt = mapPinType.get(pin.getPinType());
        mapPinType.put(pin.getPinType(), (cnt == null) ? 1 : ++cnt);
    }
    printMap(mapPinType);
}

private static void printMap(Map<String, Integer> map) {
    String key;
    int value;

    for (Map.Entry<String, Integer> entry : map.entrySet()) {
        key = entry.getKey();
        value = entry.getValue();
        System.out.println(key + ": " + value);

    }
}

答案 3 :(得分:0)

如果您不想依赖另一个库并希望保持与旧JVM的向后兼容性,这是一种可能的解决方案。它不是最好的,也不是最容易使用的,但确实有效。

<强> FrequencyUtil.java

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

public class FrequencyUtil
{
    private static FrequencyUtil SINGLETON;

    private static FrequencyUtil getInstance()
    {
        if (FrequencyUtil.SINGLETON == null)
        {
            FrequencyUtil.SINGLETON = new FrequencyUtil();
        }

        return FrequencyUtil.SINGLETON;
    }

    public static <X> Map<X, Integer> frequency(final Collection<X> objects, final Comparator<X> comparator)
    {
        Map<ComparatorWrapper<X>, Integer> frequencies = new HashMap<ComparatorWrapper<X>, Integer>();

        for (X object : objects)
        {
            ComparatorWrapper<X> wrapper = FrequencyUtil.getInstance().new ComparatorWrapper<X>(object, comparator);
            Integer count = frequencies.get(wrapper);
            frequencies.put(wrapper, (count == null) ? 1 : count + 1);
        }

        // unwrap the frequencies
        Map<X, Integer> frequenciesRaw = new HashMap<X, Integer>();

        for (ComparatorWrapper<X> wrapper : frequencies.keySet())
        {
            frequenciesRaw.put(wrapper.getObject(), frequencies.get(wrapper));
        }

        return frequenciesRaw;
    }

    private class ComparatorWrapper<Z>
    {
        private Z object;
        private Comparator<Z> comparator;

        ComparatorWrapper(final Z object, final Comparator<Z> comparator)
        {
            this.object = object;
            this.comparator = comparator;
            return;
        }

        public Z getObject()
        {
            return this.object;
        }

        @Override
        public int hashCode()
        {
            return 0;
        }

        @SuppressWarnings("unchecked")
        @Override
        public boolean equals(Object obj)
        {
            if ((obj == null) || !(obj instanceof ComparatorWrapper))
            {
                return false;
            }

            return this.comparator.compare(this.object, ((ComparatorWrapper<Z>) obj).getObject()) == 0;
        }
    }
}

<强> FrequencyTest.java

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

public class FrequencyTest
{
    public void test()
    {
        List<Pin> pins = new ArrayList<Pin>();

        Pin pin1 = new Pin();
        Pin pin2 = new Pin();
        Pin pin3 = new Pin();

        pin1.setPinType("typeA");
        pin2.setPinType("typeB");
        pin3.setPinType("typeA");

        pin1.setPinNumber("50");
        pin2.setPinNumber("50");
        pin3.setPinNumber("80");

        pin1.setInsertDate(Calendar.getInstance().getTime());
        pin2.setInsertDate(Calendar.getInstance().getTime());
        pin3.setInsertDate(Calendar.getInstance().getTime());

        pins.add(pin1);
        pins.add(pin2);
        pins.add(pin3);

        Comparator<Pin> pinTypeComparator = new Comparator<Pin>()
        {
            @Override
            public int compare(final Pin o1, final Pin o2)
            {
                return o1.getPinType().compareTo(o2.getPinType());
            }
        };

        Comparator<Pin> pinNumberComparator = new Comparator<Pin>()
        {
            @Override
            public int compare(final Pin o1, final Pin o2)
            {
                return o1.getPinNumber().compareTo(o2.getPinNumber());
            }
        };

        Comparator<Pin> insertDateComparator = new Comparator<Pin>()
        {
            private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

            @Override
            public int compare(final Pin o1, final Pin o2)
            {
                return this.sdf.format(o1.getInsertDate()).compareTo(this.sdf.format(o2.getInsertDate()));
            }
        };

        Map<Pin, Integer> pinTypeFrequency = FrequencyUtil.frequency(pins, pinTypeComparator);
        Map<Pin, Integer> pinNumberFrequency = FrequencyUtil.frequency(pins, pinNumberComparator);
        Map<Pin, Integer> insertDateFrequency = FrequencyUtil.frequency(pins, insertDateComparator);

        System.out.println("pinTypeFrequency");
        for (Pin pin : pinTypeFrequency.keySet())
        {
            System.out.println(pin.getPinType() + ": " + pinTypeFrequency.get(pin));
        }

        System.out.println();
        System.out.println("pinNumberFrequency");
        for (Pin pin : pinNumberFrequency.keySet())
        {
            System.out.println(pin.getPinNumber() + ": " + pinNumberFrequency.get(pin));
        }

        System.out.println();
        System.out.println("insertDateFrequency");
        for (Pin pin : insertDateFrequency.keySet())
        {
            System.out.println(pin.getInsertDate().toString() + ": " + insertDateFrequency.get(pin));
        }
    }

    public static void main(String[] args)
    {
        try
        {
            new FrequencyTest().test();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        System.exit(0);
    }
}

<强> Pin.java

import java.util.Date;

public class Pin
{
    private String pinNumber;
    private String pinType;
    private Date insertDate;

    public String getPinNumber()
    {
        return pinNumber;
    }

    public void setPinNumber(String pinNumber)
    {
        this.pinNumber = pinNumber;
    }

    public String getPinType()
    {
        return pinType;
    }

    public void setPinType(String pinType)
    {
        this.pinType = pinType;
    }

    public Date getInsertDate()
    {
        return insertDate;
    }

    public void setInsertDate(Date insertDate)
    {
        this.insertDate = insertDate;
    }
}

<强>输出

  

pinTypeFrequency typeB:1 typeA:2

     

pinNumberFrequency 80:1 50:2

     

insertDateFrequency Mon Jun 22 12:09:19 EDT 2015:3

仅供有趣和历史参考,Java 1.2版本:

<强> FrequencyUtil12.java

import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class FrequencyUtil
{
    private static FrequencyUtil SINGLETON;

    private static FrequencyUtil getInstance()
    {
        if (FrequencyUtil.SINGLETON == null)
        {
            FrequencyUtil.SINGLETON = new FrequencyUtil();
        }

        return FrequencyUtil.SINGLETON;
    }

    public static Map frequency(final Collection objects, final Comparator comparator)
    {
        Map frequencies = new HashMap();

        Iterator iter = objects.iterator();
        while (iter.hasNext())
        {
            Object object = iter.next();
            ComparatorWrapper wrapper = FrequencyUtil.getInstance().new ComparatorWrapper(object, comparator);
            Integer count = (Integer) frequencies.get(wrapper);
            frequencies.put(wrapper, (count == null) ? 1 : count + 1);
        }

        // unwrap the frequencies
        Map frequenciesRaw = new HashMap();

        Iterator keys = frequencies.keySet().iterator();
        while (keys.hasNext())
        {
            ComparatorWrapper wrapper = (ComparatorWrapper) keys.next();
            frequenciesRaw.put(wrapper.getObject(), frequencies.get(wrapper));
        }

        return frequenciesRaw;
    }

    private class ComparatorWrapper
    {
        private Object object;
        private Comparator comparator;

        ComparatorWrapper(final Object object, final Comparator comparator)
        {
            this.object = object;
            this.comparator = comparator;
            return;
        }

        public Object getObject()
        {
            return this.object;
        }

        public int hashCode()
        {
            return 0;
        }

        public boolean equals(Object obj)
        {
            if ((obj == null) || !(obj instanceof ComparatorWrapper))
            {
                return false;
            }

            return this.comparator.compare(this.object, ((ComparatorWrapper) obj).getObject()) == 0;
        }
    }
}