samples/effectivelist/src/org/apidesign/effectivelist/List.scala
author Jaroslav Tulach <jtulach@netbeans.org>
Fri, 31 Aug 2012 20:16:57 +0200
changeset 402 e25dbfce40e9
child 403 ebe08056c60c
permissions -rw-r--r--
Example demostrating how to use trait to provide effective implementation of linked list while keeping encapsulation
jtulach@402
     1
package org.apidesign.effectivelist
jtulach@402
     2
jtulach@402
     3
/** 
jtulach@402
     4
 * Implementation of add and remove efficient list. It has just one
jtulach@402
     5
 * restriction - its items need to carry additional information to help
jtulach@402
     6
 * the list to be effective. All items must extend trait {@link Listable}:
jtulach@402
     7
 * <pre>
jtulach@402
     8
 * <b>case class</b> Person(name : String) <b>extends</b> Listable[Person]
jtulach@402
     9
 * </pre>
jtulach@402
    10
 */
jtulach@402
    11
final class List[T <: Listable[T]] {
jtulach@402
    12
  private var item : T = _
jtulach@402
    13
  private final var EMPTY : T = _
jtulach@402
    14
  
jtulach@402
    15
  final def get(index : Int) : T = {
jtulach@402
    16
    var pos : T = item;
jtulach@402
    17
    for (i <- 1 to index) {
jtulach@402
    18
      pos = pos.next;
jtulach@402
    19
      if (pos == item) {
jtulach@402
    20
        throw new IndexOutOfBoundsException()
jtulach@402
    21
      }
jtulach@402
    22
    }
jtulach@402
    23
    return pos
jtulach@402
    24
  }
jtulach@402
    25
  
jtulach@402
    26
  final def size() : Int = {
jtulach@402
    27
    if (item == EMPTY) {
jtulach@402
    28
      return 0
jtulach@402
    29
    }
jtulach@402
    30
    var size = 0
jtulach@402
    31
    var pos : T = item
jtulach@402
    32
    do {
jtulach@402
    33
      size = size + 1
jtulach@402
    34
      pos = pos.next
jtulach@402
    35
    } while (pos != item)
jtulach@402
    36
    return size
jtulach@402
    37
  }
jtulach@402
    38
  
jtulach@402
    39
  final def add(toAdd : T) : Boolean = {
jtulach@402
    40
    if (toAdd.prev != EMPTY) {
jtulach@402
    41
      return false
jtulach@402
    42
    }
jtulach@402
    43
    
jtulach@402
    44
    if (item == null) {
jtulach@402
    45
      item = toAdd
jtulach@402
    46
      toAdd.next = toAdd
jtulach@402
    47
      toAdd.prev = toAdd
jtulach@402
    48
      return true
jtulach@402
    49
    } else {
jtulach@402
    50
      toAdd.prev = item.prev
jtulach@402
    51
      item.prev.next = toAdd
jtulach@402
    52
      item.prev = toAdd
jtulach@402
    53
      toAdd.next = item
jtulach@402
    54
      return true
jtulach@402
    55
    }
jtulach@402
    56
  }
jtulach@402
    57
  final def remove(toRemove : T) : Boolean = {
jtulach@402
    58
    if (toRemove.prev == EMPTY) {
jtulach@402
    59
      return false
jtulach@402
    60
    } else {
jtulach@402
    61
      toRemove.prev.next = toRemove.next
jtulach@402
    62
      toRemove.next.prev = toRemove.prev;
jtulach@402
    63
      if (item.next == item) {
jtulach@402
    64
        item = EMPTY
jtulach@402
    65
      }
jtulach@402
    66
      if (item == toRemove) {
jtulach@402
    67
        item = toRemove.next
jtulach@402
    68
      }
jtulach@402
    69
      toRemove.next = EMPTY
jtulach@402
    70
      toRemove.prev = EMPTY
jtulach@402
    71
      return true
jtulach@402
    72
    }
jtulach@402
    73
  }
jtulach@402
    74
}