我正在开发一个将在我公司的某些产品中使用的功能,因此我无法获得特定于产品的代码。
我将2个查询的结果存储在2个JoinRowSet
个对象上(我必须使用JoinRowSet
,因为我必须在以后加入其他查询的结果)。然后,我需要与那些JoinRowSet
相交,但我不知道他们“属于”哪个类(我不知道查询是否会返回人物,联系人,部门或任何其他东西)。我被告知我应该使用lambda表达式来做到这一点,但我发现了一些问题。
我已将JoinRowSet
中的一个转换为Collection(我不知道如何直接在JoinRowSet
上使用lambda表达式),然后我循环遍历其中一个JoinRowSet
对于此JoinRowSet
的每一列,我想获取初始Collection上与该列具有相同值的记录。但是,由于我不知道数据的类,我不能做u.getAge()
之类的事情,因为我没有属性名称。
这是我的方法:
public static void testLambdas() throws SQLException {
... //set the needed stuff to connect to database and query data
JoinRowSet jrs1 = ... //result from query 1
JoinRowSet jrs2 = ... //result from query 2
Collection<Row> jrs2Collection = (Collection<Row>) jrs2.getRowSets();//collection to use on lambda expression
while (jrs1.next()) {
ResultSetMetaData metadata = jrs1.getMetaData();
for (int j = 1; j <= metadata.getColumnCount(); j++) {
String dataType = metadata.getColumnTypeName(j);
Object colValue = null;
if (dataType.equals("NUMBER")) {
colValue = jrs1.getBigDecimal(j);
} else if (dataType.equals("VARCHAR2")) {
colValue = jrs1.getString(j);
} else if (dataType.equals("DATE")) {
colValue = jrs1.getTimestamp(j);
}
System.out.println(metadata.getColumnName(j)+ " (" + dataType +"): "+ colValue);
Object o = jrs2Collection.stream()
.filter(u -> {
try {
return (u.getColumnObject(j).equals(colValue));
} catch (Exception e) {
e.printStackTrace();
return false;
}
})
.collect(Collectors.toCollection(TreeSet::new));
}
}
}
请忽略这样一个事实,即lambda表达式的使用在一段时间内,并且不会在每次迭代时重复使用。如果我能解决现在的问题,我会照顾好。
我必须将try-catch添加到过滤器,因为它返回未处理的异常类型SQLException
。添加此try-catch后,我得到一个在封闭范围内定义的局部变量j
必须是u.getColumnObject(j)
上的最终或有效最终。
我不知道我在做什么是最好的方法,或者我做错了什么(我的同事中有两位看过我的代码,也不知道如何解决这个问题)。
我很感激有关此的任何意见。
答案 0 :(得分:2)
当你在循环中创建集合而不使用它们时,你不清楚你正在尝试做什么。所以我不能告诉你是否有更好的解决方案。
关于错误,错误消息非常清楚。您不能在lambda中使用可变局部变量。但是,解决方案非常简单:您可以将可变变量的内容分配给不可变变量:
for (int j = 1; j <= metadata.getColumnCount(); j++) {
// …
int currentJ = j;
Object currentColValue = colValue;
Object o = jrs2Collection.stream()
.filter(u -> {
try {
return (u.getColumnObject(currentJ).equals(currentColValue));
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
)
.collect(Collectors.toCollection(TreeSet::new));
}
请注意,currentJ
和currentColValue
实际上是最终的,这意味着您可以在不更改程序的情况下向其添加final
修饰符。要求在lambda表达式中使用的局部变量是final
或有效的最终。
顺便说一下,不要考虑“在迭代之间重用lambda”。在大多数情况下,JRE将尽可能重用为lambda表达式创建的实例。并且JDBC操作总是超过为lambda表达式创建的临时对象所施加的任何开销。