/* Copyright (c) 2008-2010, developers of the Ascension Log Visualizer * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ package com.googlecode.logVisualizer.util; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * This utility class counts how many times certain elements were added to it. * Note that while letting this class count big amounts of data shouldn't be a * problem, letting it count big amounts of different objects can be very memory * taxing and lessen the performance of this class. */ public final class DataCounter<E> { private final Map<E, Integer> counterBucket; private final Set<E> dataSet; /** * Constructs the DataCounter with an initial capacity for the internal hash * data containers of 20. The load factor for the internal hash data * containers is 0.75. * <p> * This constructor should be used only if the number of different objects * to be counted is known to be pretty low. */ public DataCounter() { this.counterBucket = new HashMap<>(20); this.dataSet = new HashSet<>(20); } /** * Constructs the DataCounter with the given initial capacity for the * internal hash data containers. All reglementations of both * {@link HashSet} and {@link HashMap} also come into action here. The load * factor for the internal hash data containers is 0.75. * * @param intialHashCapacity * The initial capacity of the internal hash data containers. */ public DataCounter(final int intialHashCapacity) { this.counterBucket = new HashMap<>(intialHashCapacity); this.dataSet = new HashSet<>(intialHashCapacity); } /** * Adds these objects to the counter and starts counting them, or if they * already are counted, continues to do so. * * @param elements * The objects to be counted. * @throws NullPointerException * if elements is {@code null} */ public void addDataElements(final Collection<? extends E> elements) { if (elements == null) { throw new NullPointerException( "Data element list must not be null."); } for (final E e : elements) { this.addDataElement(e); } } /** * Adds this object to the counter and starts counting it, or if it already * is counted, continues to do so. * * @param e * The object to be counted. * @throws NullPointerException * if e is {@code null} */ public void addDataElement(final E e) { this.addDataElement(e, 1); } /** * Adds this object to the counter and starts counting it, or if it already * is counted, continues to do so. * <p> * The object will be seen as being added the given {@code amount} of times. * * @param e * The object to be counted. * @param amount * The amount of the given object. * @throws NullPointerException * if e is {@code null} */ public void addDataElement(final E e, final int amount) { if (e == null) { throw new NullPointerException( "Element to be added must not be null."); } if (!this.dataSet.contains(e)) { this.dataSet.add(e); this.counterBucket.put(e, amount); } else { this.counterBucket.put(e, this.counterBucket.get(e) + amount); } } /** * Returns an unsorted list of {@link DataNumber} objects, which hold the * counted objects and how many times they appeared. * * @return The list of objects and how many times they were counted. */ public List<DataNumberPair<E>> getCountedData() { final List<DataNumberPair<E>> countedData = new ArrayList<>( this.dataSet.size()); for (final E e : this.dataSet) { countedData.add(DataNumberPair.of(e, this.counterBucket.get(e))); } return countedData; } }