|
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