import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class Ideone
{
static class RecordingEntity {
int size, ops;
RecordingEntity(int size) {
this.size = size;
}
RecordingEntity concat(RecordingEntity e) {
RecordingEntity result = new RecordingEntity(size + e.size);
// the costs of each construction scale with the result size
result.ops = ops + e.ops + result.size;
return result;
}
}
public static void main
(String[] args
) { List<RecordingEntity> input = IntStream.of(10, 20, 5, 15, 7, 3, 25)
.mapToObj(RecordingEntity::new)
.collect(Collectors.toList());
System.
out.
println("naive concatenation"); {
RecordingEntity r = input.stream().reduce(RecordingEntity::concat).get();
System.
out.
println("String of length "+r.
size+", constructed in "+r.
ops+" operations"); }
System.
out.
println("exploiting associativity (using combiner)"); {
RecordingEntity r = splitReduce(input, RecordingEntity::concat);
System.
out.
println("String of length "+r.
size+", constructed in "+r.
ops+" operations"); }
}
static <T> T splitReduce(List<T> list, BinaryOperator<T> reduce) {
if(list.size() > 3) {
int mid = list.size() >>> 1;
return reduce.apply(
splitReduce(list.subList(0, mid), reduce),
splitReduce(list.subList(mid, list.size()), reduce));
}
return list.stream().reduce(reduce).get();
}
}
aW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS51dGlsLmZ1bmN0aW9uLkJpbmFyeU9wZXJhdG9yOwppbXBvcnQgamF2YS51dGlsLnN0cmVhbS5Db2xsZWN0b3JzOwppbXBvcnQgamF2YS51dGlsLnN0cmVhbS5JbnRTdHJlYW07CgpjbGFzcyBJZGVvbmUKewogICAgc3RhdGljIGNsYXNzIFJlY29yZGluZ0VudGl0eSB7CiAgICAgICAgaW50IHNpemUsIG9wczsKCiAgICAgICAgUmVjb3JkaW5nRW50aXR5KGludCBzaXplKSB7CiAgICAgICAgICAgIHRoaXMuc2l6ZSA9IHNpemU7CiAgICAgICAgfQogICAgICAgIFJlY29yZGluZ0VudGl0eSBjb25jYXQoUmVjb3JkaW5nRW50aXR5IGUpIHsKICAgICAgICAgICAgUmVjb3JkaW5nRW50aXR5IHJlc3VsdCA9IG5ldyBSZWNvcmRpbmdFbnRpdHkoc2l6ZSArIGUuc2l6ZSk7CiAgICAgICAgICAgIC8vIHRoZSBjb3N0cyBvZiBlYWNoIGNvbnN0cnVjdGlvbiBzY2FsZSB3aXRoIHRoZSByZXN1bHQgc2l6ZQogICAgICAgICAgICByZXN1bHQub3BzID0gb3BzICsgZS5vcHMgKyByZXN1bHQuc2l6ZTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICB9CgogICAgcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgewogICAgICAgIExpc3Q8UmVjb3JkaW5nRW50aXR5PiBpbnB1dCA9IEludFN0cmVhbS5vZigxMCwgMjAsIDUsIDE1LCA3LCAzLCAyNSkKICAgICAgICAgICAgLm1hcFRvT2JqKFJlY29yZGluZ0VudGl0eTo6bmV3KQogICAgICAgICAgICAuY29sbGVjdChDb2xsZWN0b3JzLnRvTGlzdCgpKTsKCiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJuYWl2ZSBjb25jYXRlbmF0aW9uIik7CiAgICAgICAgewogICAgICAgICAgICBSZWNvcmRpbmdFbnRpdHkgciA9IGlucHV0LnN0cmVhbSgpLnJlZHVjZShSZWNvcmRpbmdFbnRpdHk6OmNvbmNhdCkuZ2V0KCk7CiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiU3RyaW5nIG9mIGxlbmd0aCAiK3Iuc2l6ZSsiLCBjb25zdHJ1Y3RlZCBpbiAiK3Iub3BzKyIgb3BlcmF0aW9ucyIpOwogICAgICAgIH0KICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oImV4cGxvaXRpbmcgYXNzb2NpYXRpdml0eSAodXNpbmcgY29tYmluZXIpIik7CiAgICAgICAgewogICAgICAgICAgICBSZWNvcmRpbmdFbnRpdHkgciA9IHNwbGl0UmVkdWNlKGlucHV0LCBSZWNvcmRpbmdFbnRpdHk6OmNvbmNhdCk7CiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiU3RyaW5nIG9mIGxlbmd0aCAiK3Iuc2l6ZSsiLCBjb25zdHJ1Y3RlZCBpbiAiK3Iub3BzKyIgb3BlcmF0aW9ucyIpOwogICAgICAgIH0KICAgIH0KICAgIHN0YXRpYyA8VD4gVCBzcGxpdFJlZHVjZShMaXN0PFQ+IGxpc3QsIEJpbmFyeU9wZXJhdG9yPFQ+IHJlZHVjZSkgewogICAgICAgIGlmKGxpc3Quc2l6ZSgpID4gMykgewogICAgICAgICAgICBpbnQgbWlkID0gbGlzdC5zaXplKCkgPj4+IDE7CiAgICAgICAgICAgIHJldHVybiByZWR1Y2UuYXBwbHkoCiAgICAgICAgICAgICAgICBzcGxpdFJlZHVjZShsaXN0LnN1Ykxpc3QoMCwgbWlkKSwgcmVkdWNlKSwKICAgICAgICAgICAgICAgIHNwbGl0UmVkdWNlKGxpc3Quc3ViTGlzdChtaWQsIGxpc3Quc2l6ZSgpKSwgcmVkdWNlKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBsaXN0LnN0cmVhbSgpLnJlZHVjZShyZWR1Y2UpLmdldCgpOwogICAgfQp9