我想知道是否有可能在Stream中拆分对象。例如,对于此Employee
:
public class Employee {
String name;
int age;
double salary;
public Employee(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() { return name; }
public int getAge() { return age; }
public double getSalary() { return salary; }
}
我想在流中执行一些操作。为简单起见,让它像这样(假设我的代码体系结构不允许将其放在Employee类中,否则太容易了):public void someOperationWithEmployee(String name, int age, double salary) {
System.out.format("%s %d %.0f\n", name, age, salary);
}
现在看起来像这样:Stream.of(new Employee("Adam", 38, 3000), new Employee("John", 19, 2000))
// some conversations go here ...
.forEach(e -> someOperationWithEmployee(e.getName, e.getAge(), e.getSalary));
问题是,是否可以在这样的流中放入一些代码?Stream.of(new Employee("Adam", 38, 3000), new Employee("John", 19, 2000))
// some conversations go here
.forEach((a, b, c) -> someOperationWithEmployee(a, b, c));
我想达到什么目的? -我认为,如果我可以映射一些对象字段,然后像.forEach(this::someOperationWithEmployee)
这样处理它们,则代码的可读性将略有提高。更新14.05.2015
毫无疑问,在这种情况下,将
Employee
对象传递给someOperationWithEmployee
是最漂亮的解决方案,但有时我们在现实生活中无法做到这一点,因此应该是lambda的通用解决方案。 最佳答案
我不确定这是否符合您的需求,但可以稍作修改,而不检查某些类型。
您可以通过以下方式运行我的解决方案:
Stream.of(new Employee("Adam", 38, 3000), new Employee("John", 19, 2000))
.forEach(
e->ArrayCaller.<TriConsumer<String, Integer, Double>>convert(e::getName, e::getAge, e::getSalary)
.call((a, b, c) -> operation(a, b, c)));
它将调用“main”类的此简单方法:
private void operation(String name, int age, double salary) {
System.out.format("%s %d %.0f\n", name, age, salary);
}
当然需要以下辅助类型:
/** Extending interfaces must have a method called consume with N args */
interface NConsumer {}
/*
* Method must be called consume for reflection.
*
* You can define N interfaces like this.
*/
nterface TriConsumer<A, B, C> extends NConsumer {
void consume(A a, B b, C c);
}
interface ArrayCaller<E extends NConsumer> {
void call(E code);
static <T extends NConsumer> ArrayCaller<T> convert(Supplier<?>...argSuppliers) {
final Object[] args = new Object[argSuppliers.length];
for (int i = 0; i < argSuppliers.length; i++) {
args[i] = argSuppliers[i].get();
}
return new ArrayCaller<T>() {
@Override
public void call(T code) {
for (Method m: code.getClass().getMethods()) {
if (m.getName().equals("consume")) {
try {
m.invoke(code, args);
} catch (IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
}
};
}
}