summaryrefslogtreecommitdiff
path: root/src/library/scalax/collection/generic/SetTemplate.scala
blob: 9c3056cc04846d2f21481278744c60eda117e385 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2003-2009, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id: Set.scala 16893 2009-01-13 13:09:22Z cunei $


package scalax.collection.generic


/** <p>
 *    A set is a collection that includes at most one of any object.
 *  </p>
 *  <p>
 *    This trait provides a limited interface, only allowing reading of elements.
 *    There are two extensions of this trait, in packages
 *    <code><a href="mutable$content.html" target="contentFrame">
 *    scala.collection.mutable</a></code>
 *    and <code><a href="immutable$content.html" target="contentFrame">
 *    scala.collection.immutable</a></code>, which provide functionality for
 *    adding and removing objects from the set. The trait in the first package is
 *    for sets that are modified destructively, whereas the trait in
 *    the second package is for immutable sets which create a new set
 *    when something is added or removed to them.
 *
 *  @author  Matthias Zenger
 *  @author  Martin Odersky
 *  @version 2.8
 */
trait SetTemplate[+CC[B] <: SetTemplate[CC, B] with Set[B], A] extends (A => Boolean) with SizedIterable[A] with OrderedIterableTemplate[CC, A] {

  /** Returns the number of elements in this set.
   *
   *  @return number of set elements.
   */
  def size: Int

  /** Creates a new set of this kind with given elements */
  def newBuilder[B]: Builder[CC, B]

  /** Checks if this set contains element <code>elem</code>.
   *
   *  @param elem the element to check for membership.
   *  @return     <code>true</code> iff <code>elem</code> is contained in
   *              this set.
   */
  def contains(elem: A): Boolean

  /** Create a new set with an additional element.
   */
  def +(elem: A): CC[A]

  /** Remove a single element from a set.
   *  @param elem the element to be removed
   *  @return a new set with the element removed.
   */
  def -(elem: A): CC[A]

  /** Checks if this set is empty.
   *
   *  @return <code>true</code> iff there is no element in the set.
   */
  override def isEmpty: Boolean = size == 0

  /** This method allows sets to be interpreted as predicates.
   *  It returns <code>true</code>, iff this set contains element
   *  <code>elem</code>.
   *
   *  @param elem the element to check for membership.
   *  @return     <code>true</code> iff <code>elem</code> is contained in
   *              this set.
   */
  def apply(elem: A): Boolean = contains(elem)

  /** Add two or more elements to this set.
   *  @param    elem1 the first element.
   *  @param    elem2 the second element.
   *  @param    elems the remaining elements.
   *  @return a new set with the elements added.
   */
  def + (elem1: A, elem2: A, elems: A*): CC[A] = {
    thisCC + elem1 + elem2 ++ elems.asInstanceOf[Iterable[A]]
  }

  /** Remove two or more elements from this set.
   *
   *  @param    elem1 the first element.
   *  @param    elem2 the second element.
   *  @param    elems the remaining elements.
   *  @return a new set with the elements removed.
   */
  def - (elem1: A, elem2: A, elems: A*): CC[A] =
    this - elem1 - elem2 -- elems.asInstanceOf[Iterable[A]]

  /** Remove all the elements provided by an iterator
   *  of the iterable object <code>elems</code> from the set.
   *
   *  @param elems An iterable object containing the elements to remove from the set.
   *  @return a new set with the elements removed.
   */
  def -- (elems: Iterable[A]): CC[A] = this -- elems.elements

  /** Remove all the elements provided by an iterator
   *  <code>elems</code> from the set.
   *
   *  @param elems An iterator containing the elements to remove from the set.
   *  @return a new set with the elements removed.
   */
  def -- (elems: Iterator[A]): CC[A] =
    (thisCC /: elems) (_ - _)

  /** This method computes an intersection with set <code>that</code>.
   *  It removes all the elements that are not present in <code>that</code>.
   *
   *  @param that the set to intersect with.
   */
  def intersect(that: Set[A]): CC[A] = filter(that.contains)

  /** This method is an alias for <code>intersect</code>.
   *  It computes an intersection with set <code>that</code>.
   *  It removes all the elements that are not present in <code>that</code>.
   *
   *  @param that the set to intersect with
   */
  def ** (that: collection.Set[A]): CC[A] = intersect(that)

  /** Checks if this set is a subset of set <code>that</code>.
   *
   *  @param that another set.
   *  @return     <code>true</code> iff the other set is a superset of
   *              this set.
   *  todo: rename to isSubsetOf
   */
  def subsetOf(that: Set[A]): Boolean = forall(that.contains)

  /** Compares this set with another object and returns true, iff the
   *  other object is also a set which contains the same elements as
   *  this set.
   *
   *  @param that the other object
   *  @note not necessarily run-time type safe.
   *  @return     <code>true</code> iff this set and the other set
   *              contain the same elements.
   *  @deprecated equals is not stable for mutable sets.
   *              If you wish object identity, use eq or cast this set of AnyRef and then use
   *              equals. If you wish element comparisons, use `sameElements` instead.
   */
  @deprecated override def equals(that: Any): Boolean = that match {
    case other: Set[_] =>
      this.size == other.size && subsetOf(other.asInstanceOf[Set[A]])
    case _ =>
      false
  }

  /*  @deprecated hashCode is not stable for mutable sets.
   *              if you intend to have object identity hashCode and wish the deprecated warning
   *              to go away, cast this set to AnyRef before calling hashCode.
   */
  @deprecated override def hashCode() =
    (0 /: this)((hash, e) => hash + e.hashCode())

  /** Defines the prefix of this object's <code>toString</code> representation.
   */
  override def stringPrefix: String = "Set"

  /** Need to override string, so that it's not the Function1's string that gets mixed in.
   */
  override def toString = super[OrderedIterableTemplate].toString
}