Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
157 views
in Technique[技术] by (71.8m points)

java - .forEach and .sort don't work and cannot set breakpoints in blocks

I am using Java 8 (build 1.8.0_25), Netbeans 8.0.2 and am incorporating some of the Java 8 features into an existing app. Sorting and .forEach is not working so I have created some test code to ensure I understand lambdas, etc. and to diagnose the problem. Below is a mix of new code as well as code to interact with the data from my system:

  public void test(Registration reg) {
/* new code */
    List<String> family = new ArrayList<>();
    family.add("Mom");
    family.add("Dad");
    family.add("Brother");
    family.add("Sister");

    family.forEach(p -> System.out.println(p));

    Collections.sort(family, (p1,p2) -> {
        System.out.println(p1 + " <==> "+ p2);
        return p1.compareToIgnoreCase(p2);
            });

    family.forEach(p -> System.out.println(p));

/* code to test with my system data */
    List<RegistrationItem> item = new ArrayList<>();
    List<RegistrationItem> regI = reg.getRegistrationItem();

    regI.forEach(p -> {
        System.out.println(p.toString());
        item.add(p);
            });

    Collections.sort(regI, (r1,r2) -> {
        System.out.println(r1.toString() + r2.toString());
        return r1.getId().compareTo(r2.getId());
    });

    for (RegistrationItem r : regI) {
            item.add(r);
    }
}

Registration is a POJO reflecting data for an event which includes a List of RegistrationItem(s) which is another POJO of details. In this test the list size is 4.

The section labelled new code works perfectly. It prints out the list, prints as it sorts and them prints the sorted list. I can also set breakpoints inside the block of the sort which is what I would expect.

The working with existing code is another matter. The .forEach and .sort don't work and I can not set breakpoints in the java 8 blocks. The debugger steps to the code but it doesn't seem like it executes. When I get to the for loop, "item" still has a size of 0. The look is just there to prove that the data can be moved which works as expected and results in a size of 4.

Any help would be appreciated.


I apologize I probably wasn't clear. This is just test code demonstrating a problem I am experiencing in dozens of places since changing to java 8. comparators were changed to lambdas and for loops to .forEach and none are working. This code has no purpose other than for this posting.

In the example, I have verified that reg is passed correctly to the test method. It is structured correctly and regI has a size of 4 with correctly structured objects.

  • The new Array list "item" is just to provide a simple container for the .forEach test
  • The .forEach is to test with a block of code and setting a breakpoint. It doesn't work.
  • The .sort is intended to re-order the list in the same container. I didn't use streams as I don't want to move it. It doesn't work
  • The for loop is to prove the old fashion way that the list has valid data and the intent of the .forEach should have worked. It DOES work as expected

I assume I have something wrong in my environment or this code but have been unable to identify it on my own.

After testing with the approach suggested by Holger and Stuart Marks, it is pretty clear that this is the same problem related to IndirectList and overrides. My JRE and JDK are both Java 8 and I have upgraded to EclipseLink 2.5.2. I have proven the problem to occur 100% of the time with comparator, Collections.sort with lambdas and .forEach. This seems like a very pervasive problem and I am surprised the other question has not attracted more attention than 1 uptick besides mine.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The root cause of this problem is the use of a flawed implementation pattern in the IndirectList class of EclipseLink JPA. (doc, source) This problem occurs in the 2.5 release family; it may also occur in other versions.

The problem is that this class both subclasses Vector and has a reference to a Vector instance. It attempts to delegate all method calls to that instance by overriding all of the methods of Vector. This works fine, as long as no new methods are added to Vector.

This happened in Java 8.

Java 8 added several new default methods to the Collection, Iterable, and List interfaces, including:

  • forEach
  • parallelStream
  • removeIf
  • replaceAll
  • sort
  • spliterator
  • stream

Typically, adding default methods is safe, since they must be implemented in terms of other existing methods. However, it is usually a good idea for implementing classes to override default methods for reasons of efficiency. The Java 8 Vector implementation added several overrides of these default methods. These work fine if you have an instance of the actual Vector class. The IndirectList class doesn't override these methods, so the delegation path that it attempted to set up doesn't work for these methods. Instead, the ordinary Vector implementations are used. Unfortunately, the IndirectList methods don't keep the superclass state up to date, so the Vector implementations of the methods all behave as if the Vector is empty.

Vector overrides forEach, removeIf, replaceAll, sort, and spliterator. The parallelStream and stream default methods are implemented in terms of spliterator, so the same thing happens to them. Essentially, none of the new default methods on collections will work if they are used on an IndirectList implementation retrieved from EclipseLink JPA.

Note that this problem also occurs with Collections.sort(indirectList). This method simply calls the indirectList.sort() method, so it encounters exactly the same problem as described above.

Some potential workarounds for this problem are listed in this answer.

For further information about the status of EclipseLink, see EclipseLink JPA bugs 433075 and 446236.

For further information about the pitfalls of this implementation pattern, see Joshua Bloch's book Effective Java, Second Edition, Item 16: Favor Composition over Inheritance.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...