@@ -87,12 +87,14 @@ public HeadersMultiMap setAll(MultiMap headers) {
8787 if (headers instanceof HeadersMultiMap ) {
8888 clear ();
8989 HeadersMultiMap that = (HeadersMultiMap ) headers ;
90- MapEntry thatHead = that .head ;
91- MapEntry curr = thatHead ;
92- while (curr .after != thatHead ) {
93- MapEntry next = curr .after ;
94- add (next .key , next .value );
95- curr = next ;
90+ MapEntry head = that .head ;
91+ MapEntry e = head ;
92+ if (e != null ) {
93+ do {
94+ add (e .key , e .value );
95+ e = e .after ;
96+ }
97+ while (e != head );
9698 }
9799 return this ;
98100 } else {
@@ -112,8 +114,8 @@ public int size() {
112114
113115 private final BiConsumer <CharSequence , CharSequence > validator ;
114116 private final HeadersMultiMap .MapEntry [] entries = new HeadersMultiMap .MapEntry [16 ];
115- private final HeadersMultiMap .MapEntry head = new HeadersMultiMap .MapEntry ();
116117 private final boolean readOnly ;
118+ private HeadersMultiMap .MapEntry head = null ;
117119 private byte [] encoded ;
118120
119121 public HeadersMultiMap () {
@@ -125,16 +127,12 @@ public HeadersMultiMap(BiConsumer<CharSequence, CharSequence> validator) {
125127 }
126128
127129 private HeadersMultiMap (boolean mutable , BiConsumer <CharSequence , CharSequence > validator ) {
128-
129- head .before = head .after = head ;
130-
131130 this .readOnly = !mutable ;
132131 this .validator = validator ;
133132 }
134133
135134 private HeadersMultiMap (boolean mutable , HeadersMultiMap that ) {
136135
137- head .before = head .after = head ;
138136 setAll ((MultiMap ) that );
139137
140138 this .readOnly = !mutable ;
@@ -373,19 +371,25 @@ public List<String> getAll(String name) {
373371
374372 @ Override
375373 public void forEach (Consumer <? super Map .Entry <String , String >> action ) {
376- HeadersMultiMap .MapEntry e = head .after ;
377- while (e != head ) {
378- action .accept (e .stringEntry ());
379- e = e .after ;
374+ MapEntry e = head ;
375+ if (e != null ) {
376+ do {
377+ action .accept (e .stringEntry ());
378+ e = e .after ;
379+ }
380+ while (e != head );
380381 }
381382 }
382383
383384 @ Override
384385 public void forEach (BiConsumer <String , String > action ) {
385- HeadersMultiMap .MapEntry e = head .after ;
386- while (e != head ) {
387- action .accept (e .getKey ().toString (), e .getValue ().toString ());
388- e = e .after ;
386+ MapEntry e = head ;
387+ if (e != null ) {
388+ do {
389+ action .accept (e .getKey ().toString (), e .getValue ().toString ());
390+ e = e .after ;
391+ }
392+ while (e != head );
389393 }
390394 }
391395
@@ -394,56 +398,99 @@ public List<Map.Entry<String, String>> entries() {
394398 return io .vertx .core .http .HttpHeaders .super .entries ();
395399 }
396400
401+ private static abstract class IteratorBase <T > implements Iterator <T > {
402+
403+ private final MapEntry head ;
404+ private MapEntry curr ;
405+
406+ public IteratorBase (MapEntry head ) {
407+ this .head = head ;
408+ this .curr = head ;
409+ }
410+
411+ @ Override
412+ public boolean hasNext () {
413+ return curr != null ;
414+ }
415+
416+ @ Override
417+ public T next () {
418+ if (curr == null ) {
419+ throw new NoSuchElementException ();
420+ }
421+ MapEntry e = curr ;
422+ MapEntry next = e .after ;
423+ curr = next == head ? null : next ;
424+ return map (e );
425+ }
426+
427+ protected abstract T map (MapEntry e );
428+
429+ }
430+
397431 @ Override
398432 public Iterator <Map .Entry <String , String >> iterator () {
399- return new Iterator <>() {
400- MapEntry curr = head ;
401- @ Override
402- public boolean hasNext () {
403- return curr .after != head ;
404- }
405- @ Override
406- public Map .Entry <String , String > next () {
407- MapEntry next = curr .after ;
408- if (next == head ){
409- throw new NoSuchElementException ();
433+ MapEntry h = head ;
434+ if (h == null ) {
435+ return Collections .emptyIterator ();
436+ } else {
437+ return new IteratorBase <>(h ) {
438+ @ Override
439+ protected Map .Entry <String , String > map (MapEntry e ) {
440+ return new Map .Entry <>() {
441+ @ Override
442+ public String getKey () {
443+ return e .key .toString ();
444+ }
445+ @ Override
446+ public String getValue () {
447+ return e .value .toString ();
448+ }
449+ @ Override
450+ public String setValue (String value ) {
451+ return e .setValue (value ).toString ();
452+ }
453+ @ Override
454+ public String toString () {
455+ return getKey () + "=" + getValue ();
456+ }
457+ };
410458 }
411- curr = next ;
412- return new Map .Entry <>() {
413- @ Override
414- public String getKey () {
415- return next .key .toString ();
416- }
417- @ Override
418- public String getValue () {
419- return next .value .toString ();
420- }
421- @ Override
422- public String setValue (String value ) {
423- return next .setValue (value ).toString ();
424- }
425- @ Override
426- public String toString () {
427- return getKey () + "=" + getValue ();
428- }
429- };
459+ };
460+ }
461+ }
462+
463+ @ Override
464+ public Iterator <Map .Entry <CharSequence , CharSequence >> iteratorCharSequence () {
465+ MapEntry h = head ;
466+ if (h == null ) {
467+ return Collections .emptyIterator ();
468+ }
469+ return new IteratorBase <>(h ) {
470+ @ Override
471+ protected Map .Entry <CharSequence , CharSequence > map (MapEntry e ) {
472+ return e ;
430473 }
431474 };
432475 }
433476
434477 @ Override
435478 public boolean isEmpty () {
436- return head == head . after ;
479+ return head == null ;
437480 }
438481
439482 @ Override
440483 public Set <String > names () {
484+ HeadersMultiMap .MapEntry e = head ;
485+ if (e == null ) {
486+ return Collections .emptySet ();
487+ }
441488 Set <String > names = new TreeSet <>(String .CASE_INSENSITIVE_ORDER );
442- HeadersMultiMap .MapEntry e = head .after ;
443- while (e != head ) {
489+ do {
444490 names .add (e .getKey ().toString ());
445491 e = e .after ;
446492 }
493+ while (e != head );
447494 return names ;
448495 }
449496
@@ -453,7 +500,7 @@ public HeadersMultiMap clear() {
453500 throw new IllegalStateException ("Read only" );
454501 }
455502 Arrays .fill (entries , null );
456- head . before = head . after = head ;
503+ head = null ;
457504 return this ;
458505 }
459506
@@ -495,23 +542,6 @@ public long getTimeMillis(CharSequence name, long defaultValue) {
495542 throw new UnsupportedOperationException ();
496543 }
497544
498- @ Override
499- public Iterator <Map .Entry <CharSequence , CharSequence >> iteratorCharSequence () {
500- return new Iterator <Map .Entry <CharSequence , CharSequence >>() {
501- HeadersMultiMap .MapEntry current = head .after ;
502- @ Override
503- public boolean hasNext () {
504- return current != head ;
505- }
506- @ Override
507- public Map .Entry <CharSequence , CharSequence > next () {
508- Map .Entry <CharSequence , CharSequence > next = current ;
509- current = current .after ;
510- return next ;
511- }
512- };
513- }
514-
515545 @ Override
516546 public HttpHeaders addInt (CharSequence name , int value ) {
517547 throw new UnsupportedOperationException ();
@@ -549,11 +579,16 @@ public void encode(ByteBuf buf) {
549579 }
550580
551581 private void encode0 (ByteBuf buf ) {
552- HeadersMultiMap .MapEntry current = head .after ;
553- while (current != head ) {
554- encodeHeader (current .key , current .value , buf );
555- current = current .after ;
582+ MapEntry h = head ;
583+ if (h == null ) {
584+ return ;
556585 }
586+ HeadersMultiMap .MapEntry c = h ;
587+ do {
588+ encodeHeader (c .key , c .value , buf );
589+ c = c .after ;
590+ }
591+ while (c != h );
557592 }
558593
559594 private static final int COLON_AND_SPACE_SHORT = (COLON << 8 ) | SP ;
@@ -603,20 +638,6 @@ private final class MapEntry implements Map.Entry<CharSequence, CharSequence> {
603638 this .value = value ;
604639 }
605640
606- void remove () {
607- before .after = after ;
608- after .before = before ;
609- after = null ;
610- before = null ;
611- }
612-
613- void addBefore (HeadersMultiMap .MapEntry e ) {
614- after = e ;
615- before = e .before ;
616- before .after = this ;
617- after .before = this ;
618- }
619-
620641 @ Override
621642 public CharSequence getKey () {
622643 return key ;
@@ -671,7 +692,17 @@ private void remove0(int h, int i, CharSequence name) {
671692 } else {
672693 prev .next = next ;
673694 }
674- e .remove ();
695+ if (e == head ) {
696+ if (head .after == head ) {
697+ head = null ;
698+ } else {
699+ head = head .after ;
700+ }
701+ }
702+ e .before .after = e .after ;
703+ e .after .before = e .before ;
704+ e .after = null ;
705+ e .before = null ;
675706 } else {
676707 prev = e ;
677708 }
@@ -693,7 +724,16 @@ private void add0(int h, int i, final CharSequence name, final CharSequence valu
693724 newEntry .next = e ;
694725
695726 // Update the linked list.
696- newEntry .addBefore (head );
727+ if (head == null ) {
728+ head = newEntry ;
729+ newEntry .after = newEntry ;
730+ newEntry .before = newEntry ;
731+ } else {
732+ newEntry .after = head ;
733+ newEntry .before = head .before ;
734+ head .before .after = newEntry ;
735+ head .before = newEntry ;
736+ }
697737 }
698738
699739 private HeadersMultiMap set0 (final CharSequence name , final CharSequence strVal ) {
0 commit comments