001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.common.collection; 017 018import java.util.AbstractCollection; 019import java.util.AbstractMap; 020import java.util.AbstractSequentialList; 021import java.util.AbstractSet; 022import java.util.ArrayList; 023import java.util.Collection; 024import java.util.HashMap; 025import java.util.HashSet; 026import java.util.Iterator; 027import java.util.LinkedList; 028import java.util.List; 029import java.util.ListIterator; 030import java.util.Map; 031import java.util.NoSuchElementException; 032import java.util.Set; 033import java.util.concurrent.atomic.AtomicInteger; 034import org.modeshape.common.util.ObjectUtil; 035 036/** 037 * A {@link Multimap} implementation that uses an {@link LinkedList} to store the values associated with a key. This 038 * implementation allows duplicate values for a key, maintains the insertion-order of the {@link #get(Object) values for each key} 039 * , and maintains the insertion order of all {@link #entries() key-value pairs}. 040 * 041 * @param <K> the key type 042 * @param <V> the value type 043 */ 044public final class LinkedListMultimap<K, V> implements ListMultimap<K, V> { 045 046 /** 047 * Creates a new, empty {@code LinkedListMultimap} with the default initial capacity. 048 * 049 * @param <K> the key type 050 * @param <V> the value type 051 * @return the new linked-list multimap; never null 052 */ 053 public static <K, V> LinkedListMultimap<K, V> create() { 054 return new LinkedListMultimap<K, V>(); 055 } 056 057 protected static final class Entry<K, V> { 058 final K key; 059 V value; 060 Entry<K, V> nextWithKey; 061 Entry<K, V> previousWithKey; 062 Entry<K, V> next; 063 Entry<K, V> previous; 064 065 protected Entry( K key, 066 V value ) { 067 this.key = key; 068 this.value = value; 069 } 070 071 /** 072 * {@inheritDoc} 073 * 074 * @see java.lang.Object#toString() 075 */ 076 @Override 077 public String toString() { 078 return "[" + key + "=" + value + "]"; 079 } 080 } 081 082 protected Entry<K, V> firstEntry; 083 protected Entry<K, V> lastEntry; 084 protected int length; 085 protected final Map<K, AtomicInteger> numberOfEntriesForKey; 086 protected final Map<K, Entry<K, V>> firstEntryWithKey; 087 protected final Map<K, Entry<K, V>> lastEntryWithKey; 088 089 private transient Map<K, Collection<V>> mapView; 090 091 protected LinkedListMultimap() { 092 this.firstEntryWithKey = new HashMap<K, Entry<K, V>>(); 093 this.lastEntryWithKey = new HashMap<K, Entry<K, V>>(); 094 this.numberOfEntriesForKey = new HashMap<K, AtomicInteger>(); 095 } 096 097 @Override 098 public void clear() { 099 length = 0; 100 firstEntryWithKey.clear(); 101 lastEntryWithKey.clear(); 102 } 103 104 @Override 105 public int size() { 106 return length; 107 } 108 109 @Override 110 public boolean isEmpty() { 111 return length == 0; 112 } 113 114 @Override 115 public boolean containsKey( K key ) { 116 return firstEntryWithKey.containsKey(key); 117 } 118 119 @Override 120 public boolean containsEntry( Object key, 121 Object value ) { 122 @SuppressWarnings( "unchecked" ) 123 ValueIterator values = new ValueIterator((K)key); 124 while (values.hasNext()) { 125 if (ObjectUtil.isEqualWithNulls(values.next(), value)) return true; 126 } 127 return false; 128 } 129 130 @Override 131 public boolean containsValue( Object value ) { 132 EntryIterator entries = new EntryIterator(); 133 while (entries.hasNext()) { 134 if (ObjectUtil.isEqualWithNulls(entries.next().value, value)) return true; 135 } 136 return false; 137 } 138 139 @Override 140 public List<V> get( final K key ) { 141 return new AbstractSequentialList<V>() { 142 @Override 143 public int size() { 144 return currentCountFor(key); 145 } 146 147 @Override 148 public ListIterator<V> listIterator( int index ) { 149 return new ValueIterator(key, index); 150 } 151 }; 152 } 153 154 @Override 155 public boolean put( K key, 156 V value ) { 157 addEntryFor(key, value); 158 return true; 159 } 160 161 @Override 162 public boolean remove( K key, 163 V value ) { 164 // Find the entry with the value ... 165 ValueIterator values = new ValueIterator(key); 166 while (values.hasNext()) { 167 if (ObjectUtil.isEqualWithNulls(values.next(), value)) { 168 values.remove(); 169 return true; 170 } 171 } 172 return false; 173 } 174 175 @Override 176 public Collection<V> removeAll( K key ) { 177 // Find the entries with the value ... 178 List<V> result = new ArrayList<V>(currentCountFor(key)); 179 ValueIterator values = new ValueIterator(key); 180 while (values.hasNext()) { 181 result.add(values.next()); 182 values.remove(); 183 } 184 return result; 185 } 186 187 @Override 188 public Collection<Map.Entry<K, V>> entries() { 189 return new AbstractCollection<Map.Entry<K, V>>() { 190 @Override 191 public int size() { 192 return length; 193 } 194 195 @Override 196 public Iterator<Map.Entry<K, V>> iterator() { 197 return new Iterator<Map.Entry<K, V>>() { 198 private final EntryIterator iter = new EntryIterator(); 199 200 @Override 201 public boolean hasNext() { 202 return iter.hasNext(); 203 } 204 205 @Override 206 public Map.Entry<K, V> next() { 207 Entry<K, V> next = iter.next(); 208 return new ImmutableMapEntry<K, V>(next.key, next.value); 209 } 210 211 @Override 212 public void remove() { 213 iter.remove(); 214 } 215 }; 216 } 217 }; 218 } 219 220 @Override 221 public Set<K> keySet() { 222 return new AbstractSet<K>() { 223 @Override 224 public int size() { 225 return numberOfEntriesForKey.size(); 226 } 227 228 @Override 229 public Iterator<K> iterator() { 230 return new KeyIterator(); 231 } 232 }; 233 } 234 235 @Override 236 public Collection<V> values() { 237 return new AbstractCollection<V>() { 238 @Override 239 public int size() { 240 return length; 241 } 242 243 @Override 244 public Iterator<V> iterator() { 245 return new Iterator<V>() { 246 private final EntryIterator iter = new EntryIterator(); 247 248 @Override 249 public boolean hasNext() { 250 return iter.hasNext(); 251 } 252 253 @Override 254 public V next() { 255 Entry<K, V> next = iter.next(); 256 return next.value; 257 } 258 259 @Override 260 public void remove() { 261 iter.remove(); 262 } 263 }; 264 } 265 }; 266 } 267 268 @Override 269 public Map<K, Collection<V>> asMap() { 270 if (mapView == null) mapView = new MapView(); 271 return mapView; 272 } 273 274 protected class MapView extends AbstractMap<K, Collection<V>> { 275 276 private Set<Map.Entry<K, Collection<V>>> entries; 277 278 @Override 279 public Set<Map.Entry<K, Collection<V>>> entrySet() { 280 if (entries == null) entries = new MapEntries(); 281 return entries; 282 } 283 } 284 285 protected class MapEntries extends AbstractSet<Map.Entry<K, Collection<V>>> { 286 @Override 287 public int size() { 288 return length; 289 } 290 291 @Override 292 public Iterator<Map.Entry<K, Collection<V>>> iterator() { 293 return new Iterator<Map.Entry<K, Collection<V>>>() { 294 private KeyIterator iter = new KeyIterator(); 295 296 @Override 297 public boolean hasNext() { 298 return iter.hasNext(); 299 } 300 301 @Override 302 public Map.Entry<K, Collection<V>> next() { 303 final K nextKey = iter.next(); 304 return new ImmutableMapEntry<K, Collection<V>>(nextKey, null) { 305 @Override 306 public Collection<V> getValue() { 307 return get(nextKey); 308 } 309 }; 310 } 311 312 @Override 313 public void remove() { 314 iter.remove(); 315 } 316 }; 317 } 318 } 319 320 @Override 321 public int hashCode() { 322 return asMap().hashCode(); 323 } 324 325 @Override 326 public boolean equals( Object obj ) { 327 if (obj == this) return true; 328 if (obj instanceof Multimap) { 329 Multimap<?, ?> that = (Multimap<?, ?>)obj; 330 return this.asMap().equals(that.asMap()); 331 } 332 return false; 333 } 334 335 @Override 336 public String toString() { 337 return asMap().toString(); 338 } 339 340 protected int incrementEntryCountFor( K key ) { 341 AtomicInteger count = numberOfEntriesForKey.get(key); 342 if (count == null) { 343 count = new AtomicInteger(0); 344 numberOfEntriesForKey.put(key, count); 345 } 346 ++length; 347 return count.incrementAndGet(); 348 } 349 350 protected int decrementEntryCountFor( K key ) { 351 AtomicInteger count = numberOfEntriesForKey.get(key); 352 assert count != null; 353 int result = count.decrementAndGet(); 354 if (result == 0) numberOfEntriesForKey.remove(key); 355 --length; 356 return result; 357 } 358 359 protected int currentCountFor( K key ) { 360 AtomicInteger count = numberOfEntriesForKey.get(key); 361 return count != null ? count.get() : 0; 362 } 363 364 protected Entry<K, V> addEntryFor( K key, 365 V value ) { 366 Entry<K, V> entry = new Entry<K, V>(key, value); 367 if (firstEntry == null) { 368 assert length == 0; 369 // This is the first entry ... 370 firstEntry = entry; 371 firstEntryWithKey.put(key, entry); 372 } else { 373 // Add this entry to the end ... 374 lastEntry.next = entry; 375 entry.previous = lastEntry; 376 // Find the last entry with this key ... 377 Entry<K, V> lastWithKey = lastEntryWithKey.get(key); 378 if (lastWithKey == null) { 379 // This is the first entry for this key ... 380 firstEntryWithKey.put(key, entry); 381 } 382 } 383 384 // This entry is always the last entry ... 385 Entry<K, V> previousLastWithKey = lastEntryWithKey.put(key, entry); 386 if (previousLastWithKey != null) { 387 previousLastWithKey.nextWithKey = entry; 388 entry.previousWithKey = previousLastWithKey; 389 } 390 lastEntry = entry; 391 incrementEntryCountFor(key); 392 return entry; 393 } 394 395 protected Entry<K, V> insertEntryBefore( K key, 396 V value, 397 Entry<K, V> nextEntryWithKey ) { 398 if (nextEntryWithKey == null) return addEntryFor(key, value); 399 400 // Otherwise the new entry will lever be last ... 401 Entry<K, V> entry = new Entry<K, V>(key, value); 402 assert firstEntry != null; 403 assert length != 0; 404 // Set the entry's references ... 405 entry.next = nextEntryWithKey; 406 entry.nextWithKey = nextEntryWithKey; 407 entry.previous = nextEntryWithKey.previous; 408 entry.previousWithKey = nextEntryWithKey.previousWithKey; 409 // Set the reference from the entry that WAS before the next entry ... 410 if (nextEntryWithKey.previousWithKey != null) { 411 // This will NOT be the first entry for this key ... 412 nextEntryWithKey.previousWithKey.nextWithKey = entry; 413 } else { 414 // This will be the first entry for this key ... 415 firstEntryWithKey.put(key, entry); 416 } 417 if (nextEntryWithKey.previous != null) { 418 // This will NOT be the first entry ... 419 nextEntryWithKey.previous.next = entry; 420 } else { 421 // This will be the first entry ... 422 firstEntry = entry; 423 } 424 // Set the reference from the next entry ... 425 nextEntryWithKey.previousWithKey = entry; 426 nextEntryWithKey.previous = entry; 427 incrementEntryCountFor(key); 428 return entry; 429 } 430 431 protected void removeEntry( Entry<K, V> entry ) { 432 if (entry.previous == null) { 433 // The entry was the first ... 434 assert firstEntry == entry; 435 firstEntry = entry.next; 436 } else { 437 // Just a normal entry that is not at the front ... 438 entry.previous.next = entry.next; 439 } 440 if (entry.next == null) { 441 // The entry was the last ... 442 assert lastEntry == entry; 443 lastEntry = entry.previous; 444 } else { 445 // Just a normal entry that is not at the ed ... 446 entry.next.previous = entry.previous; 447 } 448 if (entry.previousWithKey != null) { 449 entry.previousWithKey.nextWithKey = entry.nextWithKey; 450 } else if (entry.nextWithKey != null) { 451 // We're removing the first entry with the key, and there is a next entry with the key .. 452 firstEntryWithKey.put(entry.key, entry.nextWithKey); 453 } else { 454 // We're removing the first and only entry with the key ... 455 firstEntryWithKey.remove(entry.key); 456 } 457 if (entry.nextWithKey != null) { 458 entry.nextWithKey.previousWithKey = entry.previousWithKey; 459 } else if (entry.previousWithKey != null) { 460 // We're removing the last entry with the key, and there is a previoius entry with the key .. 461 lastEntryWithKey.put(entry.key, entry.previousWithKey); 462 } else { 463 // We're removing the last and only entry with the key ... 464 lastEntryWithKey.remove(entry.key); 465 } 466 decrementEntryCountFor(entry.key); 467 } 468 469 protected void isValid( Entry<K, V> entry ) { 470 if (entry == null) throw new NoSuchElementException(); 471 } 472 473 protected class EntryIterator implements Iterator<Entry<K, V>> { 474 private Entry<K, V> nextEntry; 475 private Entry<K, V> currentEntry; 476 477 protected EntryIterator() { 478 nextEntry = firstEntry; 479 } 480 481 protected EntryIterator( Entry<K, V> first ) { 482 nextEntry = first; 483 } 484 485 @Override 486 public boolean hasNext() { 487 return nextEntry != null; 488 } 489 490 @Override 491 public Entry<K, V> next() { 492 isValid(nextEntry); 493 currentEntry = nextEntry; 494 nextEntry = nextEntry.next; 495 return currentEntry; 496 } 497 498 @Override 499 public void remove() { 500 if (currentEntry == null) throw new IllegalStateException(); 501 removeEntry(currentEntry); 502 currentEntry = null; 503 } 504 } 505 506 protected class ValueIterator implements ListIterator<V> { 507 private Entry<K, V> previous; 508 private Entry<K, V> current; 509 private Entry<K, V> next; 510 private int nextIndex; 511 private final K key; 512 513 protected ValueIterator( K key ) { 514 this.key = key; 515 next = firstEntryWithKey.get(key); 516 nextIndex = 0; 517 } 518 519 protected ValueIterator( K key, 520 int index ) { 521 this.key = key; 522 int count = currentCountFor(key); 523 if (index > count / 2) { 524 // The index is closer to the end, so start at the end .. 525 previous = lastEntryWithKey.get(key); 526 nextIndex = count; 527 while (index++ < count) { 528 previous(); 529 } 530 } else { 531 // The index is closer to the front, so start at the front ... 532 next = firstEntryWithKey.get(key); 533 nextIndex = 0; 534 while (index-- > 0) { 535 next(); 536 } 537 } 538 } 539 540 @Override 541 public boolean hasNext() { 542 return next != null; 543 } 544 545 @Override 546 public V next() { 547 isValid(next); 548 current = next; 549 previous = next; 550 next = current.nextWithKey; 551 ++nextIndex; 552 return current.value; 553 } 554 555 @Override 556 public int nextIndex() { 557 return nextIndex; 558 } 559 560 @Override 561 public boolean hasPrevious() { 562 return previous != null; 563 } 564 565 @Override 566 public V previous() { 567 isValid(previous); 568 current = previous; 569 next = previous; 570 previous = current.previousWithKey; 571 --nextIndex; 572 return current.value; 573 } 574 575 @Override 576 public int previousIndex() { 577 return nextIndex - 1; 578 } 579 580 @Override 581 public void remove() { 582 if (current == null) throw new IllegalStateException(); 583 if (current != next) { 584 // removing next element 585 previous = current.previousWithKey; 586 nextIndex--; 587 } else { 588 next = current.nextWithKey; 589 } 590 removeEntry(current); 591 current = null; 592 } 593 594 @Override 595 public void add( V value ) { 596 if (next == null) { 597 previous = addEntryFor(key, value); 598 } else { 599 previous = insertEntryBefore(key, value, next); 600 } 601 nextIndex++; 602 current = null; 603 } 604 605 @Override 606 public void set( V value ) { 607 if (current == null) throw new IllegalStateException(); 608 current.value = value; 609 } 610 } 611 612 protected class KeyIterator implements Iterator<K> { 613 private final Set<K> seen = new HashSet<K>(); 614 private Entry<K, V> next = firstEntry; 615 private Entry<K, V> current = null; 616 617 @Override 618 public boolean hasNext() { 619 return next != null; 620 } 621 622 @Override 623 public K next() { 624 if (next == null) throw new NoSuchElementException(); 625 current = next; 626 seen.add(current.key); 627 do { 628 next = next.next; 629 } while (next != null && !seen.add(next.key)); 630 return current.key; 631 } 632 633 @Override 634 public void remove() { 635 if (current == null) throw new NoSuchElementException(); 636 removeAll(current.key); 637 current = null; 638 } 639 } 640 641}