这是我的实际for-each循环。我需要将其转换为java8 for循环。
for (PromotionEntity promotionEntity : pestudents) {
List<ClassAttendanceChild> attendancelist = session.createQuery("from ClassAttendanceChild where attendanceadded='" + day + "' and pid.pId='" + promotionEntity.getpId() + "'").list();
if (!attendancelist.isEmpty()) {
ClassAttendanceChild attendenceDetails = (ClassAttendanceChild) attendancelist.get(0);
if (attendenceDetails.getStatus().equalsIgnoreCase("yes")) {
present++;
System.out.println("present = " + present);
} else {
Absent++;
System.out.println("Absent = " + Absent);
}
} else {
nottaken++;
System.out.println("nottaken = " + nottaken);
}
}
如何将其转换为java8 for循环,我在该变量增量中得到异常:
pestudents.forEach(promotionEntity -> {
List<ClassAttendanceChild> attendancelist = session.createQuery("from ClassAttendanceChild where attendanceadded='" + day + "' and pid.pId='" + promotionEntity.getpId() + "'").list();
if (!attendancelist.isEmpty()) {
ClassAttendanceChild attendenceDetails = (ClassAttendanceChild) attendancelist.get(0);
if (attendenceDetails.getStatus().equalsIgnoreCase("yes")) {
// present++;
// System.out.println("present = " + present);
} else {
// Absent++;
// System.out.println("Absent = " + Absent);
}
} else {
// nottaken++;
// System.out.println("nottaken = " + nottaken);
}
});
答案 0 :(得分:4)
像往常一样,当您决定实现功能时,您必须回到更高级别的目标描述,然后以FP风格重写代码。
您想确定三类事件的总数:“现在”,“缺席”和“未记录”。以下是关于如何通过FP方式实现它的建议(感谢Stuart Marks指出如何构建库提供的频率计数收集器):
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
...
System.out.println(pestudents.stream().collect(groupingBy(pe -> {
final List<ClassAttendanceChild> attendancelist = session.createQuery(
"from ClassAttendanceChild where attendanceadded='" + day
+ "' and pid.pId='" + promotionEntity.getpId() + "'")
.list();
return attendancelist.isEmpty()? "nottaken"
: attendancelist.get(0).getStatus().equalsIgnoreCase("yes")?
"present" : "absent";
}, counting())));
您可以注意到我们已将工作分为两个阶段:首先我们对每个PromotionEntity
进行分类,然后对这些进行频率计数减少。结果是从类别到其计数的映射。
对我而言,意图的清晰度足以具有FP风格的优势,但这具有为并行化准备地形的额外优势。在这种特殊情况下,并行化可能不会得到回报,因为瓶颈是数据库,但一般来说,如果全程采用FP风格,则并行化将成为更接近目标。
public static void main(String[] args) {
final List<PromotionEntity> pestudents = ...your initialization...
final Map<String, Integer> freqs = pestudents.stream().map(pe -> {
final List<ClassAttendanceChild> attendancelist = session.createQuery(
"from ClassAttendanceChild where attendanceadded='" + day +
"' and pid.pId='" + promotionEntity.getpId() + "'")
.list();
return attendancelist.isEmpty()? "nottaken"
: attendancelist.get(0).getStatus().equalsIgnoreCase("yes")?
"present" : "absent";
}).collect(toFrequencyMap());
System.out.println(freqs);
}
static Integer zeroForNull(Integer i) { return i == null? 0 : i; }
static <K> Collector<K, Map<K, Integer>, Map<K, Integer>> toFrequencyMap() {
return Collector.of(
HashMap<K, Integer>::new,
(acc, key) -> acc.compute(key, (x, count) -> zeroForNull(count) + 1),
(acc, source) -> {
source.forEach((key, sourceCount) ->
acc.compute(key, (x,accCount) ->
sourceCount + zeroForNull(accCount)));
return acc;
},
Collector.Characteristics.UNORDERED);
}
答案 1 :(得分:1)
要并行化此代码,您可以使用AtomicInteger作为线程安全计数器。
AtomicInteger present = new AtomicInteger();
AtomicInteger absent = new AtomicInteger();
AtomicInteger nottaken = new AtomicInteger();
pestudents.parallelStream().forEach(promotionEntity -> {
List<ClassAttendanceChild> attendancelist = session.createQuery("from ClassAttendanceChild where attendanceadded='" + day + "' and pid.pId='" + promotionEntity.getpId() + "'").list();
if (!attendancelist.isEmpty()) {
ClassAttendanceChild attendenceDetails = (ClassAttendanceChild) attendancelist.get(0);
if (attendenceDetails.getStatus().equalsIgnoreCase("yes")) {
present.incrementAndGet();
System.out.println("present = " + present);
} else {
absent.incrementAndGet();
System.out.println("Absent = " + Absent);
}
} else {
nottaken.incrementAndGet();
System.out.println("nottaken = " + nottaken);
}
});
答案 2 :(得分:0)
不允许修改传递给forEach
的方法之外定义的局部变量。必须将它们声明为final
或至少有效地最终,这意味着它们在初始化后永远不会更改。
您可以做的是将present
和其他局部变量更改为实例变量或类变量,允许您修改它们。
那就是说,我建议你保留旧语法,它更适合你想要做的事情。