import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class Test {
static class DataPoint {
private long timestamp;
public DataPoint
(long timestamp,
Object value
) { this.timestamp = timestamp;
this.value = value;
}
public long getTimestamp() {
return timestamp;
}
return value;
}
return timestamp + ": " + value;
}
}
static class NamedKeeparator implements Iterator<DataPoint> {
private final Iterator<DataPoint> delegate;
private DataPoint current;
public NamedKeeparator
(String name, Iterator
<DataPoint
> delegate
) { this.delegate = delegate;
this.name = name;
}
@Override
public boolean hasNext() {
return delegate.hasNext();
}
@Override
public DataPoint next() {
return current = delegate.next();
}
public DataPoint current() {
return current;
}
public void consume() {
current = null;
}
return name;
}
}
public static void main
(String args
[]) { Map
<String, List
<DataPoint
>> metriDps
= new HashMap
<>(); "m1", "m2", "m3"
};
List<DataPoint> dataPoints1 = new ArrayList<DataPoint>();
dataPoints1.add(new DataPoint(0, 1));
dataPoints1.add(new DataPoint(2, 1));
dataPoints1.add(new DataPoint(3, 5));
metriDps.put("m1", dataPoints1);
List<DataPoint> dataPoints2 = new ArrayList<DataPoint>();
dataPoints2.add(new DataPoint(1, 2));
dataPoints2.add(new DataPoint(2, 3));
dataPoints2.add(new DataPoint(3, 5));
metriDps.put("m2", dataPoints2);
List<DataPoint> dataPoints3 = new ArrayList<DataPoint>();
dataPoints3.add(new DataPoint(0, 2));
dataPoints3.add(new DataPoint(2, 6));
dataPoints3.add(new DataPoint(4, 5));
metriDps.put("m3", dataPoints3);
// header
writer.append("timestamp,");
writer.append(Stream.of(metricNames).collect(Collectors.joining(",")));
writer.append('\n');
List<NamedKeeparator> iterators = metriDps.entrySet().stream()
.map(entry -> new NamedKeeparator(entry.getKey(), entry.getValue().iterator()))
.collect(Collectors.toList());
List<NamedKeeparator> leastIterators = new ArrayList<>();
for (;;) {
leastIterators.clear();
long leastValue
= Long.
MAX_VALUE; for (NamedKeeparator iterator : iterators) {
// advance until there is some value
while (iterator.current() == null && iterator.hasNext()) {
iterator.next();
}
// build set of iterators pointing to least value
if (iterator.current() != null
&& iterator.current().getTimestamp() <= leastValue) {
if (iterator.current().getTimestamp() < leastValue) {
leastValue = iterator.current().getTimestamp();
leastIterators.clear();
}
leastIterators.add(iterator);
}
}
// nothing -> all iterators done
if (leastIterators.isEmpty())
break;
// least contains now iterators for the same timestamp
// get time from the first
long time = leastIterators.get(0).current().getTimestamp();
writer.
append(String.
valueOf(time
)).
append(',');
// format points
String points
= Stream.
of(metricNames
) .map(metric -> leastIterators.stream()
.filter(it -> it.getName().equals(metric)).findAny()
.map(it -> it.current()).orElse(null))
.
map(point
-> point
!= null ? String.
valueOf(point.
getValue()) : "") .collect(Collectors.joining(","));
writer.append(points).append('\n');
leastIterators.forEach(it -> {
it.consume();
});
}
}
}