4040import java .util .Locale ;
4141import java .util .Map ;
4242import java .util .Set ;
43- import java .util .SortedSet ;
44- import java .util .TreeSet ;
4543import java .util .WeakHashMap ;
4644import java .util .concurrent .ConcurrentHashMap ;
4745
@@ -153,8 +151,8 @@ public class HtmlPage extends SgmlPage {
153151 private transient Charset originalCharset_ ;
154152 private final Object lock_ = new SerializableLock (); // used for synchronization
155153
156- private Map <String , SortedSet < DomElement > > idMap_ = new ConcurrentHashMap <>();
157- private Map <String , SortedSet < DomElement > > nameMap_ = new ConcurrentHashMap <>();
154+ private Map <String , MappedElementIndexEntry > idMap_ = new ConcurrentHashMap <>();
155+ private Map <String , MappedElementIndexEntry > nameMap_ = new ConcurrentHashMap <>();
158156
159157 private List <BaseFrameElement > frameElements_ = new ArrayList <>();
160158 private int parserCount_ ;
@@ -629,7 +627,7 @@ public ProcessingInstruction createProcessingInstruction(final String namespaceU
629627 @ Override
630628 public DomElement getElementById (final String elementId ) {
631629 if (elementId != null ) {
632- final SortedSet < DomElement > elements = idMap_ .get (elementId );
630+ final MappedElementIndexEntry elements = idMap_ .get (elementId );
633631 if (elements != null ) {
634632 return elements .first ();
635633 }
@@ -1665,9 +1663,9 @@ public <E extends HtmlElement> E getHtmlElementById(final String elementId) thro
16651663 */
16661664 public List <DomElement > getElementsById (final String elementId ) {
16671665 if (elementId != null ) {
1668- final SortedSet < DomElement > elements = idMap_ .get (elementId );
1666+ final MappedElementIndexEntry elements = idMap_ .get (elementId );
16691667 if (elements != null ) {
1670- return new ArrayList <>(elements );
1668+ return new ArrayList <>(elements . elements () );
16711669 }
16721670 }
16731671 return Collections .emptyList ();
@@ -1685,7 +1683,7 @@ public List<DomElement> getElementsById(final String elementId) {
16851683 @ SuppressWarnings ("unchecked" )
16861684 public <E extends DomElement > E getElementByName (final String name ) throws ElementNotFoundException {
16871685 if (name != null ) {
1688- final SortedSet < DomElement > elements = nameMap_ .get (name );
1686+ final MappedElementIndexEntry elements = nameMap_ .get (name );
16891687 if (elements != null ) {
16901688 return (E ) elements .first ();
16911689 }
@@ -1703,9 +1701,9 @@ public <E extends DomElement> E getElementByName(final String name) throws Eleme
17031701 */
17041702 public List <DomElement > getElementsByName (final String name ) {
17051703 if (name != null ) {
1706- final SortedSet < DomElement > elements = nameMap_ .get (name );
1704+ final MappedElementIndexEntry elements = nameMap_ .get (name );
17071705 if (elements != null ) {
1708- return new ArrayList <>(elements );
1706+ return new ArrayList <>(elements . elements () );
17091707 }
17101708 }
17111709 return Collections .emptyList ();
@@ -1722,14 +1720,14 @@ public List<DomElement> getElementsByIdAndOrName(final String idAndOrName) {
17221720 if (idAndOrName == null ) {
17231721 return Collections .emptyList ();
17241722 }
1725- final Collection < DomElement > list1 = idMap_ .get (idAndOrName );
1726- final Collection < DomElement > list2 = nameMap_ .get (idAndOrName );
1723+ final MappedElementIndexEntry list1 = idMap_ .get (idAndOrName );
1724+ final MappedElementIndexEntry list2 = nameMap_ .get (idAndOrName );
17271725 final List <DomElement > list = new ArrayList <>();
17281726 if (list1 != null ) {
1729- list .addAll (list1 );
1727+ list .addAll (list1 . elements () );
17301728 }
17311729 if (list2 != null ) {
1732- for (final DomElement elt : list2 ) {
1730+ for (final DomElement elt : list2 . elements () ) {
17331731 if (!list .contains (elt )) {
17341732 list .add (elt );
17351733 }
@@ -1804,14 +1802,14 @@ void addMappedElement(final DomElement element, final boolean recurse) {
18041802 }
18051803 }
18061804
1807- private void addElement (final Map <String , SortedSet < DomElement > > map , final DomElement element ,
1805+ private void addElement (final Map <String , MappedElementIndexEntry > map , final DomElement element ,
18081806 final String attribute , final boolean recurse ) {
18091807 final String value = element .getAttribute (attribute );
18101808
18111809 if (ATTRIBUTE_NOT_DEFINED != value ) {
1812- SortedSet < DomElement > elements = map .get (value );
1810+ MappedElementIndexEntry elements = map .get (value );
18131811 if (elements == null ) {
1814- elements = new TreeSet <>( DOCUMENT_POSITION_COMPERATOR );
1812+ elements = new MappedElementIndexEntry ( );
18151813 elements .add (element );
18161814 map .put (value , elements );
18171815 }
@@ -1845,14 +1843,13 @@ void removeMappedElement(final DomElement element, final boolean recurse, final
18451843 }
18461844 }
18471845
1848- private void removeElement (final Map <String , SortedSet < DomElement > > map , final DomElement element ,
1846+ private void removeElement (final Map <String , MappedElementIndexEntry > map , final DomElement element ,
18491847 final String attribute , final boolean recurse ) {
18501848 final String value = element .getAttribute (attribute );
18511849
18521850 if (ATTRIBUTE_NOT_DEFINED != value ) {
1853- final SortedSet <DomElement > elements = map .remove (value );
1854- if (elements != null && (elements .size () != 1 || !elements .contains (element ))) {
1855- elements .remove (element );
1851+ final MappedElementIndexEntry elements = map .remove (value );
1852+ if (elements != null && elements .remove (element )) {
18561853 map .put (value , elements );
18571854 }
18581855 }
@@ -2879,4 +2876,54 @@ private void readObject(final ObjectInputStream in) throws IOException, ClassNot
28792876 computedStyles_ = new WeakHashMap <>();
28802877 }
28812878 }
2879+
2880+ private static final class MappedElementIndexEntry {
2881+ private ArrayList <DomElement > elements_ ;
2882+ private boolean sorted_ ;
2883+
2884+ MappedElementIndexEntry () {
2885+ // we do not expect to many elements having the same id/name
2886+ elements_ = new ArrayList <>(2 );
2887+ sorted_ = false ;
2888+ }
2889+
2890+ void add (final DomElement element ) {
2891+ elements_ .add (element );
2892+ sorted_ = false ;
2893+ }
2894+
2895+ DomElement first () {
2896+ if (elements_ .size () == 0 ) {
2897+ return null ;
2898+ }
2899+
2900+ if (sorted_ ) {
2901+ return elements_ .get (0 );
2902+ }
2903+
2904+ Collections .sort (elements_ , DOCUMENT_POSITION_COMPERATOR );
2905+ sorted_ = true ;
2906+
2907+ return elements_ .get (0 );
2908+ }
2909+
2910+ List <DomElement > elements () {
2911+ if (sorted_ || elements_ .size () == 0 ) {
2912+ return elements_ ;
2913+ }
2914+
2915+ Collections .sort (elements_ , DOCUMENT_POSITION_COMPERATOR );
2916+ sorted_ = true ;
2917+
2918+ return elements_ ;
2919+ }
2920+
2921+ boolean remove (final DomElement element ) {
2922+ if (elements_ .size () == 0 ) {
2923+ return false ;
2924+ }
2925+
2926+ return elements_ .remove (element );
2927+ }
2928+ }
28822929}
0 commit comments