我将从Java8中的流API开始。
public class Person {
private String firstName;
private String lastName;
private int age;
private double height;
private double weight;
public Person(String firstName, String lastName, int age, double height, double weight) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.height = height;
this.weight = weight;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public double getHeight() {
return height;
}
public double getWeight() {
return weight;
}
}
List<Person> personsList = new ArrayList<Person>();
personsList.add(new Person("John", "Doe", 25, 1.80, 80));
personsList.add(new Person("Jane", "Doe", 30, 1.69, 60));
personsList.add(new Person("John", "Smith", 35, 174, 70));
long count = personsList.stream().filter(p -> p.getFirstName().equals("John")).count();
int maxAge = personsList.stream().mapToInt(Person::getAge).max().getAsInt();
double minHeight = personsList.stream().mapToDouble(Person::getHeight).min().getAsDouble();
double avgWeight = personsList.stream().mapToDouble(Person::getWeight).average().getAsDouble();
Object[] result = new Object[] { count, maxAge, minHeight, avgWeight };
System.out.println(Arrays.toString(result));
Object[] result = personsList.stream()...count()...max()...min()...average()
我测试了Tricore
和Tagir Valeev
的解决方案,并计算了每个解决方案的运行时间。
看来Tricore
解决方案比Tagir Valeev
更有效。
Tagir Valeev
的解决方案似乎比我的解决方案(使用多个流)节省不了多少时间。
public class StreamTest {
public static class Person {
private String firstName;
private String lastName;
private int age;
private double height;
private double weight;
public Person(String firstName, String lastName, int age, double height, double weight) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.height = height;
this.weight = weight;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public double getHeight() {
return height;
}
public double getWeight() {
return weight;
}
}
public static abstract class Process {
public void run() {
StopWatch timer = new StopWatch();
timer.start();
doRun();
timer.stop();
System.out.println(timer.getTime());
}
protected abstract void doRun();
}
public static void main(String[] args) {
List<Person> personsList = new ArrayList<Person>();
for (int i = 0; i < 1000000; i++) {
int age = random(15, 60);
double height = random(1.50, 2.00);
double weight = random(50.0, 100.0);
personsList.add(new Person(randomString(10, Mode.ALPHA), randomString(10, Mode.ALPHA), age, height, weight));
}
personsList.add(new Person("John", "Doe", 25, 1.80, 80));
personsList.add(new Person("Jane", "Doe", 30, 1.69, 60));
personsList.add(new Person("John", "Smith", 35, 174, 70));
personsList.add(new Person("John", "T", 45, 179, 99));
// Query with mutiple Streams
new Process() {
protected void doRun() {
queryJava8(personsList);
}
}.run();
// Query with 'TriCore' method
new Process() {
protected void doRun() {
queryJava8_1(personsList);
}
}.run();
// Query with 'Tagir Valeev' method
new Process() {
protected void doRun() {
queryJava8_2(personsList);
}
}.run();
}
// --------------------
// JAVA 8
// --------------------
private static void queryJava8(List<Person> personsList) {
long count = personsList.stream().filter(p -> p.getFirstName().equals("John")).count();
int maxAge = personsList.stream().mapToInt(Person::getAge).max().getAsInt();
double minHeight = personsList.stream().mapToDouble(Person::getHeight).min().getAsDouble();
double avgWeight = personsList.stream().mapToDouble(Person::getWeight).average().getAsDouble();
Object[] result = new Object[] { count, maxAge, minHeight, avgWeight };
System.out.println("Java8: " + Arrays.toString(result));
}
// --------------------
// JAVA 8_1 - TriCore
// --------------------
private static void queryJava8_1(List<Person> personsList) {
Object[] objects = personsList.stream().collect(Collector.of(() -> new PersonStatistics(p -> p.getFirstName().equals("John")),
PersonStatistics::accept, PersonStatistics::combine, PersonStatistics::toStatArray));
System.out.println("Java8_1: " + Arrays.toString(objects));
}
public static class PersonStatistics {
private long firstNameCounter;
private int maxAge = Integer.MIN_VALUE;
private double minHeight = Double.MAX_VALUE;
private double totalWeight;
private long total;
private final Predicate<Person> firstNameFilter;
public PersonStatistics(Predicate<Person> firstNameFilter) {
Objects.requireNonNull(firstNameFilter);
this.firstNameFilter = firstNameFilter;
}
public void accept(Person p) {
if (this.firstNameFilter.test(p)) {
firstNameCounter++;
}
this.maxAge = Math.max(p.getAge(), maxAge);
this.minHeight = Math.min(p.getHeight(), minHeight);
this.totalWeight += p.getWeight();
this.total++;
}
public PersonStatistics combine(PersonStatistics personStatistics) {
this.firstNameCounter += personStatistics.firstNameCounter;
this.maxAge = Math.max(personStatistics.maxAge, maxAge);
this.minHeight = Math.min(personStatistics.minHeight, minHeight);
this.totalWeight += personStatistics.totalWeight;
this.total += personStatistics.total;
return this;
}
public Object[] toStatArray() {
return new Object[] { firstNameCounter, maxAge, minHeight, total == 0 ? 0 : totalWeight / total };
}
}
// --------------------
// JAVA 8_2 - Tagir Valeev
// --------------------
private static void queryJava8_2(List<Person> personsList) {
// @formatter:off
Collector<Person, ?, Object[]> collector = multiCollector(
filtering(p -> p.getFirstName().equals("John"), Collectors.counting()),
Collectors.collectingAndThen(Collectors.mapping(Person::getAge, Collectors.maxBy(Comparator.naturalOrder())), Optional::get),
Collectors.collectingAndThen(Collectors.mapping(Person::getHeight, Collectors.minBy(Comparator.naturalOrder())), Optional::get),
Collectors.averagingDouble(Person::getWeight)
);
// @formatter:on
Object[] result = personsList.stream().collect(collector);
System.out.println("Java8_2: " + Arrays.toString(result));
}
/**
* Returns a collector which combines the results of supplied collectors
* into the Object[] array.
*/
@SafeVarargs
public static <T> Collector<T, ?, Object[]> multiCollector(Collector<T, ?, ?>... collectors) {
@SuppressWarnings("unchecked")
Collector<T, Object, Object>[] cs = (Collector<T, Object, Object>[]) collectors;
// @formatter:off
return Collector.<T, Object[], Object[]> of(
() -> Stream.of(cs).map(c -> c.supplier().get()).toArray(),
(acc, t) -> IntStream.range(0, acc.length).forEach(
idx -> cs[idx].accumulator().accept(acc[idx], t)),
(acc1, acc2) -> IntStream.range(0, acc1.length)
.mapToObj(idx -> cs[idx].combiner().apply(acc1[idx], acc2[idx])).toArray(),
acc -> IntStream.range(0, acc.length)
.mapToObj(idx -> cs[idx].finisher().apply(acc[idx])).toArray());
// @formatter:on
}
/**
* filtering() collector (which will be added in JDK-9, see JDK-8144675)
*/
public static <T, A, R> Collector<T, A, R> filtering(Predicate<? super T> filter, Collector<T, A, R> downstream) {
BiConsumer<A, T> accumulator = downstream.accumulator();
Set<Characteristics> characteristics = downstream.characteristics();
return Collector.of(downstream.supplier(), (acc, t) -> {
if (filter.test(t))
accumulator.accept(acc, t);
} , downstream.combiner(), downstream.finisher(), characteristics.toArray(new Collector.Characteristics[characteristics.size()]));
}
// --------------------
// HELPER METHODS
// --------------------
public static enum Mode {
ALPHA,
ALPHANUMERIC,
NUMERIC
}
private static String randomString(int length, Mode mode) {
StringBuffer buffer = new StringBuffer();
String characters = "";
switch (mode) {
case ALPHA:
characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
break;
case ALPHANUMERIC:
characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
break;
case NUMERIC:
characters = "1234567890";
break;
}
int charactersLength = characters.length();
for (int i = 0; i < length; i++) {
double index = Math.random() * charactersLength;
buffer.append(characters.charAt((int) index));
}
return buffer.toString();
}
private static int random(int min, int max) {
Random rand = new Random();
return rand.nextInt((max - min) + 1) + min;
}
private static double random(double min, double max) {
return min + Math.random() * (max - min);
}
}
这是收集器
public class PersonStatistics {
private long firstNameCounter;
private int maxAge = Integer.MIN_VALUE;
private double minHeight = Double.MAX_VALUE;
private double totalWeight;
private long total;
private final Predicate<Person> firstNameFilter;
public PersonStatistics(Predicate<Person> firstNameFilter) {
Objects.requireNonNull(firstNameFilter);
this.firstNameFilter = firstNameFilter;
}
public void accept(Person p) {
if (this.firstNameFilter.test(p)) {
firstNameCounter++;
}
this.maxAge = Math.max(p.getAge(), maxAge);
this.minHeight = Math.min(p.getHeight(), minHeight);
this.totalWeight += p.getWeight();
this.total++;
}
public PersonStatistics combine(PersonStatistics personStatistics) {
this.firstNameCounter += personStatistics.firstNameCounter;
this.maxAge = Math.max(personStatistics.maxAge, maxAge);
this.minHeight = Math.min(personStatistics.minHeight, minHeight);
this.totalWeight += personStatistics.totalWeight;
this.total += personStatistics.total;
return this;
}
public Object[] toStatArray() {
return new Object[]{firstNameCounter, maxAge, minHeight, total == 0 ? 0 : totalWeight / total};
}
}
您可以按照以下方式使用此收集器
public class PersonMain {
public static void main(String[] args) {
List<Person> personsList = new ArrayList<>();
personsList.add(new Person("John", "Doe", 25, 180, 80));
personsList.add(new Person("Jane", "Doe", 30, 169, 60));
personsList.add(new Person("John", "Smith", 35, 174, 70));
personsList.add(new Person("John", "T", 45, 179, 99));
Object[] objects = personsList.stream().collect(Collector.of(
() -> new PersonStatistics(p -> p.getFirstName().equals("John")),
PersonStatistics::accept,
PersonStatistics::combine,
PersonStatistics::toStatArray));
System.out.println(Arrays.toString(objects));
}
}
我从8Java的Stream API开始。 这是我使用的Person对象: 这是我的代码,它初始化对象列表Person并获取对象的数量、最大年龄和最小年龄,最后创建一个包含这三个值的对象数组: 是否可以对方法进行一次调用并直接返回对象数组?
问题内容: 我试图找到与当前正在查看的标签相关的标签。我们索引中的每个文档都被标记。每个标签由两部分组成-ID和文本名称: 要获取相关标签,我只是查询文档并获取其标签的集合: 这非常有效,我得到了想要的结果。但是,我需要标签ID 和 名称才能执行任何有用的操作。我已经探索了如何做到这一点,解决方案似乎是: 索引时合并字段 将字段拼凑在一起的脚本 嵌套聚合 选项1和2对我不可用,因此我一直在使用3,
这工作得很完美,我得到了我想要的结果。但是,我需要标记ID和名称来做任何有用的事情。我已经探索了如何实现这一点,解决方案似乎是: 索引时合并字段 将字段集中在一起的脚本 嵌套聚合 选项一和选项二对我来说是不可用的,所以我一直在用3,但它没有以预期的方式做出反应。给定以下查询(仍在搜索还标记有“饼干”的文档): 我会得到这个结果: 嵌套聚合包括搜索项和我要搜索的标记(按字母顺序返回)。 我曾试图通过
问题内容: 我想验证以下行为的方法如下。 在我的@Test类中,我希望做这样的事情来验证是否使用“ exception.message”和再次使用“ exception.detail”进行了调用 但是Mockito抱怨如下 我如何告诉Mockito检查两个值? 问题答案: 进一步的阅读使我尝试使用ArgumentCaptors和以下作品,尽管比我想要的更为冗长。
我有一个Laravel 5.8项目,我需要加入3个表来显示一些结果。 基本上,我已经将所有自定义id存储在一个名为的表中。 例如,这里有两个自定义ID,我需要检索它们的: 所以我试了一下: 但这是错误的,并向我展示了错误: SQLSTATE[42000]:语法错误或访问冲突:1066不唯一 所以我需要这样说: 然后: 我该怎么做呢?
我正处于复杂的聚合查询(具有查找和许多组/展开阶段)的中间,并且遇到来自不同字段的两个不同数组的合并问题。 至于现在,在其中一个阶段之后(在我的大查询的中间或查找之后),我有以下输出: 我想: 因此,每个值,我想根据它的索引添加到内的每个对象,比如第一个内的应该有第一个来自 具有数组索引的架构): 问题是: 我无法在聚合之后或之前执行此操作,因为: > 我没有必要的数据,因为它是从不同集合中查找的