@@ -291,7 +291,7 @@ public boolean isAncestorOf(ConfigurationPropertyName name) {
291291 if (getNumberOfElements () >= name .getNumberOfElements ()) {
292292 return false ;
293293 }
294- return elementsEqual (name );
294+ return endsWithElementsEqualTo (name );
295295 }
296296
297297 @ Override
@@ -357,10 +357,20 @@ public boolean equals(Object obj) {
357357 && other .elements .canShortcutWithSource (ElementType .UNIFORM )) {
358358 return toString ().equals (other .toString ());
359359 }
360- return elementsEqual (other );
360+ if (hashCode () != other .hashCode ()) {
361+ return false ;
362+ }
363+ if (toStringMatches (toString (), other .toString ())) {
364+ return true ;
365+ }
366+ return endsWithElementsEqualTo (other );
367+ }
368+
369+ private boolean toStringMatches (String s1 , String s2 ) {
370+ return s1 .hashCode () == s2 .hashCode () && s1 .equals (s2 );
361371 }
362372
363- private boolean elementsEqual (ConfigurationPropertyName name ) {
373+ private boolean endsWithElementsEqualTo (ConfigurationPropertyName name ) {
364374 for (int i = this .elements .getSize () - 1 ; i >= 0 ; i --) {
365375 if (elementDiffers (this .elements , name .elements , i )) {
366376 return false ;
@@ -508,19 +518,7 @@ public int hashCode() {
508518 Elements elements = this .elements ;
509519 if (hashCode == 0 && elements .getSize () != 0 ) {
510520 for (int elementIndex = 0 ; elementIndex < elements .getSize (); elementIndex ++) {
511- int elementHashCode = 0 ;
512- boolean indexed = elements .getType (elementIndex ).isIndexed ();
513- int length = elements .getLength (elementIndex );
514- for (int i = 0 ; i < length ; i ++) {
515- char ch = elements .charAt (elementIndex , i );
516- if (!indexed ) {
517- ch = Character .toLowerCase (ch );
518- }
519- if (ElementsParser .isAlphaNumeric (ch )) {
520- elementHashCode = 31 * elementHashCode + ch ;
521- }
522- }
523- hashCode = 31 * hashCode + elementHashCode ;
521+ hashCode = 31 * hashCode + elements .hashCode (elementIndex );
524522 }
525523 this .hashCode = hashCode ;
526524 }
@@ -737,7 +735,7 @@ private static class Elements {
737735
738736 private static final ElementType [] NO_TYPE = {};
739737
740- public static final Elements EMPTY = new Elements ("" , 0 , NO_POSITION , NO_POSITION , NO_TYPE , null );
738+ public static final Elements EMPTY = new Elements ("" , 0 , NO_POSITION , NO_POSITION , NO_TYPE , null , null );
741739
742740 private final CharSequence source ;
743741
@@ -749,6 +747,8 @@ private static class Elements {
749747
750748 private final ElementType [] type ;
751749
750+ private final int [] hashCode ;
751+
752752 /**
753753 * Contains any resolved elements or can be {@code null} if there aren't any.
754754 * Resolved elements allow us to modify the element values in some way (or example
@@ -759,30 +759,35 @@ private static class Elements {
759759 */
760760 private final CharSequence [] resolved ;
761761
762- Elements (CharSequence source , int size , int [] start , int [] end , ElementType [] type , CharSequence [] resolved ) {
762+ Elements (CharSequence source , int size , int [] start , int [] end , ElementType [] type , int [] hashCode ,
763+ CharSequence [] resolved ) {
763764 this .source = source ;
764765 this .size = size ;
765766 this .start = start ;
766767 this .end = end ;
767768 this .type = type ;
769+ this .hashCode = (hashCode != null ) ? hashCode : new int [size ];
768770 this .resolved = resolved ;
769771 }
770772
771773 Elements append (Elements additional ) {
772774 int size = this .size + additional .size ;
773775 ElementType [] type = new ElementType [size ];
776+ int [] hashCode = new int [size ];
774777 System .arraycopy (this .type , 0 , type , 0 , this .size );
775778 System .arraycopy (additional .type , 0 , type , this .size , additional .size );
779+ System .arraycopy (this .hashCode , 0 , hashCode , 0 , this .size );
780+ System .arraycopy (additional .hashCode , 0 , hashCode , this .size , additional .size );
776781 CharSequence [] resolved = newResolved (0 , size );
777782 for (int i = 0 ; i < additional .size ; i ++) {
778783 resolved [this .size + i ] = additional .get (i );
779784 }
780- return new Elements (this .source , size , this .start , this .end , type , resolved );
785+ return new Elements (this .source , size , this .start , this .end , type , hashCode , resolved );
781786 }
782787
783788 Elements chop (int size ) {
784789 CharSequence [] resolved = newResolved (0 , size );
785- return new Elements (this .source , size , this .start , this .end , this .type , resolved );
790+ return new Elements (this .source , size , this .start , this .end , this .type , this . hashCode , resolved );
786791 }
787792
788793 Elements subElements (int offset ) {
@@ -794,7 +799,9 @@ Elements subElements(int offset) {
794799 System .arraycopy (this .end , offset , end , 0 , size );
795800 ElementType [] type = new ElementType [size ];
796801 System .arraycopy (this .type , offset , type , 0 , size );
797- return new Elements (this .source , size , start , end , type , resolved );
802+ int [] hashCode = new int [size ];
803+ System .arraycopy (this .hashCode , offset , hashCode , 0 , size );
804+ return new Elements (this .source , size , start , end , type , hashCode , resolved );
798805 }
799806
800807 private CharSequence [] newResolved (int offset , int size ) {
@@ -839,6 +846,25 @@ ElementType getType(int index) {
839846 return this .type [index ];
840847 }
841848
849+ int hashCode (int index ) {
850+ int hashCode = this .hashCode [index ];
851+ if (hashCode == 0 ) {
852+ boolean indexed = getType (index ).isIndexed ();
853+ int length = getLength (index );
854+ for (int i = 0 ; i < length ; i ++) {
855+ char ch = charAt (index , i );
856+ if (!indexed ) {
857+ ch = Character .toLowerCase (ch );
858+ }
859+ if (ElementsParser .isAlphaNumeric (ch )) {
860+ hashCode = 31 * hashCode + ch ;
861+ }
862+ }
863+ this .hashCode [index ] = hashCode ;
864+ }
865+ return hashCode ;
866+ }
867+
842868 CharSequence getSource () {
843869 return this .source ;
844870 }
@@ -951,7 +977,7 @@ else if (!type.isIndexed() && ch == this.separator) {
951977 type = ElementType .NON_UNIFORM ;
952978 }
953979 add (start , length , type , valueProcessor );
954- return new Elements (this .source , this .size , this .start , this .end , this .type , this .resolved );
980+ return new Elements (this .source , this .size , this .start , this .end , this .type , null , this .resolved );
955981 }
956982
957983 private ElementType updateType (ElementType existingType , char ch , int index ) {
0 commit comments