com.davidbracewell.collection.Counters Maven / Gradle / Ivy
Show all versions of mango Show documentation
/*
* (c) 2005 David B. Bracewell
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.davidbracewell.collection;
import com.davidbracewell.conversion.Convert;
import com.davidbracewell.conversion.Val;
import com.davidbracewell.io.resource.Resource;
import com.davidbracewell.io.structured.ElementType;
import com.davidbracewell.io.structured.StructuredFormat;
import com.davidbracewell.io.structured.StructuredReader;
import com.davidbracewell.tuple.Tuple2;
import lombok.NonNull;
import java.io.IOException;
import java.util.EnumSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
/**
* Common methods for reading counters from structured files, creating synchronized and unmodifiable wrappers, and
* creating collectors.
*/
public interface Counters {
/**
* Creates a Counter collector that count the items in a string generating a {@link HashMapCounter}.
*
* @param the type parameter
* @return the collector
*/
static Collector, Counter> collector() {
return new CounterCollector<>();
}
/**
* Creates a Counter collector that count the items in a string generating a Counter using the given supplier.
*
* @param the type parameter
* @param supplier the supplier to use for creating a counter
* @return the collector
*/
static Collector, Counter> collector(@NonNull Supplier> supplier) {
return new CounterCollector<>(supplier);
}
/**
* Creates a Counter whose keys are Integers and values are associated value in the given double array.
*
* @param array the array
* @return the counter
*/
static Counter createVectorCounter(@NonNull double[] array) {
Counter counter = new HashMapCounter<>();
for (int i = 0; i < array.length; i++) {
counter.set(i, array[i]);
}
return counter;
}
/**
* Reads a resource in the given {@link StructuredFormat} which is made up of key value pairs where the key is the
* item in the counter and the value is its count.
*
* @param the item type
* @param structuredFormat the format of the file being read
* @param resource the resource of the file being read
* @param keyType the class of the item type
* @return the counter
* @throws IOException Something went wrong reading in the counter.
*/
static Counter read(@NonNull StructuredFormat structuredFormat, @NonNull Resource resource, @NonNull Class keyType) throws IOException {
return read(structuredFormat, resource, str -> Convert.convert(str, keyType), HashMapCounter::new);
}
/**
* Reads a resource in the given {@link StructuredFormat} which is made up of key value pairs where the key is the
* item in the counter and the value is its count.
*
* @param the item type
* @param structuredFormat the format of the file being read
* @param resource the resource of the file being read
* @param deserializer Function to turn string representation of key into an item
* @param supplier the supplier to use for creating the initial counter
* @return the counter
* @throws IOException Something went wrong reading in the counter.
*/
static Counter read(@NonNull StructuredFormat structuredFormat, @NonNull Resource resource, @NonNull Function deserializer, @NonNull Supplier> supplier) throws IOException {
Counter counter = supplier.get();
try (StructuredReader reader = structuredFormat.createReader(resource)) {
reader.beginDocument();
while (reader.peek() != ElementType.END_DOCUMENT) {
Tuple2 keyValue = reader.nextKeyValue();
counter.set(deserializer.apply(keyValue.v1), keyValue.v2.asDouble());
}
reader.endDocument();
}
return counter;
}
/**
* Reads a counter from a CSV file.
*
* @param the item type
* @param resource the resource that the counter values are written to.
* @param keyClass the class of the item type
* @return the counter
* @throws IOException Something went wrong reading in the counter.
*/
static Counter readCSV(@NonNull Resource resource, @NonNull Class keyClass) throws IOException {
return read(StructuredFormat.CSV, resource, keyClass);
}
/**
* Reads a counter from a Json file.
*
* @param the item type
* @param resource the resource that the counter values are written to.
* @param keyClass the class of the item type
* @return the counter
* @throws IOException Something went wrong reading in the counter.
*/
static Counter readJson(@NonNull Resource resource, @NonNull Class keyClass) throws IOException {
return read(StructuredFormat.JSON, resource, keyClass);
}
/**
* Wraps a counter making each method call synchronized.
*
* @param the item type
* @param counter the counter to wrap
* @return the wrapped counter
*/
static Counter synchronizedCounter(@NonNull Counter counter) {
return new SynchronizedCounter<>(counter);
}
/**
* Wraps a counter making its entries unmodifiable.
*
* @param the item type
* @param counter the counter to wrap
* @return the wrapped counter
*/
static Counter unmodifiableCounter(@NonNull final Counter counter) {
return new UnmodifiableCounter<>(counter);
}
/**
* {@link Collector} implementation for Counters.
*
* @param The item type of the Counter
*/
class CounterCollector implements Collector, Counter> {
/**
* The Supplier.
*/
final Supplier> supplier;
/**
* Instantiates a new Counter collector.
*/
public CounterCollector() {
this(HashMapCounter::new);
}
/**
* Instantiates a new Counter collector.
*
* @param supplier the supplier
*/
public CounterCollector(Supplier> supplier) {
this.supplier = supplier;
}
@Override
public BiConsumer, T> accumulator() {
return Counter::increment;
}
@Override
public Set characteristics() {
return EnumSet.of(Characteristics.UNORDERED);
}
@Override
public BinaryOperator> combiner() {
return Counter::merge;
}
@Override
public Function, Counter> finisher() {
return c -> c;
}
@Override
public Supplier> supplier() {
return supplier;
}
}
}//END OF Counters