|
8 | 8 | import java.lang.invoke.MethodHandles;
|
9 | 9 | import java.util.Arrays;
|
10 | 10 | import java.util.Iterator;
|
11 |
| -import java.util.LinkedList; |
12 | 11 | import java.util.List;
|
13 | 12 | import java.util.Map;
|
| 13 | +import java.util.NoSuchElementException; |
14 | 14 |
|
15 | 15 | import jakarta.validation.ElementKind;
|
16 | 16 | import jakarta.validation.Path;
|
@@ -44,9 +44,11 @@ public class NodeImpl
|
44 | 44 | private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
|
45 | 45 |
|
46 | 46 | static final NodeImpl ROOT_NODE;
|
| 47 | + |
47 | 48 | static {
|
48 | 49 | ROOT_NODE = NodeImpl.createBeanNode( null );
|
49 | 50 | ROOT_NODE.valueSet = true;
|
| 51 | + ROOT_NODE.nodes = new NodeImpl[] { ROOT_NODE }; |
50 | 52 | ROOT_NODE.hashCode();
|
51 | 53 | }
|
52 | 54 |
|
@@ -81,6 +83,7 @@ public class NodeImpl
|
81 | 83 |
|
82 | 84 | private int hashCode = -1;
|
83 | 85 | private String asString;
|
| 86 | + private NodeImpl[] nodes; |
84 | 87 |
|
85 | 88 | private NodeImpl(
|
86 | 89 | String name, NodeImpl parent, boolean isIterable, Integer index, Object key, ElementKind kind, Class<?>[] parameterTypes,
|
@@ -568,17 +571,16 @@ boolean isRootPath() {
|
568 | 571 |
|
569 | 572 | @Override
|
570 | 573 | public Iterator<Path.Node> iterator() {
|
571 |
| - // TODO: keep the initialized list so next iterator calls can reuse it? |
572 |
| - if ( parent == null ) { |
573 |
| - return List.of( (Path.Node) this ).iterator(); |
574 |
| - } |
575 |
| - List<Path.Node> result = new LinkedList<>(); |
576 |
| - NodeImpl curr = this; |
577 |
| - while ( !curr.isRootPath() ) { |
578 |
| - result.add( 0, curr ); |
579 |
| - curr = curr.parent; |
| 574 | + if ( nodes == null ) { |
| 575 | + nodes = new NodeImpl[size - 1]; |
| 576 | + NodeImpl curr = this; |
| 577 | + while ( curr.parent != null ) { |
| 578 | + nodes[curr.size - 2] = curr; |
| 579 | + curr = curr.parent; |
| 580 | + } |
580 | 581 | }
|
581 |
| - return result.iterator(); |
| 582 | + |
| 583 | + return new NodeIterator( nodes ); |
582 | 584 | }
|
583 | 585 |
|
584 | 586 | boolean isSubPathOf(NodeImpl other) {
|
@@ -649,4 +651,26 @@ boolean samePath(NodeImpl other) {
|
649 | 651 |
|
650 | 652 | return curr == null && otherCurr == null;
|
651 | 653 | }
|
| 654 | + |
| 655 | + private static class NodeIterator implements Iterator<Path.Node> { |
| 656 | + private final NodeImpl[] array; |
| 657 | + private int index; |
| 658 | + |
| 659 | + public NodeIterator(NodeImpl[] array) { |
| 660 | + this.array = array; |
| 661 | + } |
| 662 | + |
| 663 | + @Override |
| 664 | + public boolean hasNext() { |
| 665 | + return index < array.length; |
| 666 | + } |
| 667 | + |
| 668 | + @Override |
| 669 | + public Path.Node next() { |
| 670 | + if ( index < array.length ) { |
| 671 | + return array[index++]; |
| 672 | + } |
| 673 | + throw new NoSuchElementException(); |
| 674 | + } |
| 675 | + } |
652 | 676 | }
|
0 commit comments