View Javadoc

1   /*
2    * Created on Apr 2, 2006
3    *
4    * Copyright (c) 2006, the JUNG Project and the Regents of the University 
5    * of California
6    * All rights reserved.
7    *
8    * This software is open-source under the BSD license; see either
9    * "license.txt" or
10   * http://jung.sourceforge.net/license.txt for a description.
11   */
12  package edu.uci.ics.jung.graph.util;
13  
14  import java.io.Serializable;
15  import java.util.Collection;
16  import java.util.Iterator;
17  
18  
19  /**
20   * An implementation of <code>Collection</code> that stores exactly
21   * 2 non-null objects and is not mutable.  They respect <code>equals</code>
22   * and may be used as indices or map keys.<p>
23   * Note that they do not protect from malevolent behavior: if one or another
24   * object in the tuple is mutable, then it can be changed with the usual bad
25   * effects.
26   */
27  @SuppressWarnings("serial")
28  public final class Pair<T> implements Collection<T>, Serializable
29  {
30      private T first;
31      private T second;
32  
33      /**
34       * Creates a <code>Pair</code> from the specified elements.
35       * @param value1 the first value in the new <code>Pair</code>
36       * @param value2 the second value in the new <code>Pair</code>
37       * @throws IllegalArgumentException if either argument is null
38       */
39      public Pair(T value1, T value2) 
40      {
41      	if(value1 == null || value2 == null) 
42      		throw new IllegalArgumentException("Pair cannot contain null values");
43          first = value1;
44          second = value2;
45      }
46      
47      /**
48       * Creates a Pair from the passed Collection.
49       * The size of the Collection must be 2.
50       * @param values the elements of the new <code>Pair</code>
51       * @throws IllegalArgumentException if the input collection is null,
52       * contains null values, or has != 2 elements.
53       */
54      public Pair(Collection<? extends T> values) 
55      {
56          if (values == null)
57              throw new IllegalArgumentException("Input collection cannot be null");
58      	if (values.size() == 2)
59          {
60              if(values.contains(null)) 
61                  throw new IllegalArgumentException("Pair cannot contain null values");
62              Iterator<? extends T> iter = values.iterator();
63              first = iter.next();
64              second = iter.next();
65         }
66          else
67              throw new IllegalArgumentException("Pair may only be created from a Collection of exactly 2 elements");
68          
69      }
70      
71      /**
72       * Creates a <code>Pair</code> from the passed array.
73       * The size of the array must be 2.
74       * @throws IllegalArgumentException if the input array is null,
75       * contains null values, or has != 2 elements.
76       */
77      public Pair(T[] values)
78      {
79          if (values == null)
80              throw new IllegalArgumentException("Input array cannot be null");
81          if (values.length == 2)
82          {
83              if(values[0] == null || values[1] == null) 
84                  throw new IllegalArgumentException("Pair cannot contain null values");
85              first = values[0];
86              second = values[1];
87          }
88          else
89              throw new IllegalArgumentException("Pair may only be created from an " +
90              		"array of 2 elements");
91      }
92  
93      /**
94       * Returns the first element.
95       */
96      public T getFirst() 
97      {
98          return first;
99      }
100     
101     /**
102      * Returns the second element.
103      */
104     public T getSecond() 
105     {
106         return second;
107     }
108     
109     @SuppressWarnings("unchecked")
110     @Override
111     public boolean equals( Object o ) {
112         if (o == this)
113             return true;
114 
115         if (o instanceof Pair) {
116             Pair otherPair = (Pair) o;
117             Object otherFirst = otherPair.getFirst();
118             Object otherSecond = otherPair.getSecond();
119             return 
120             	(this.first  == otherFirst  || 
121             			(this.first != null  && this.first.equals(otherFirst)))   
122             			&&
123                 (this.second == otherSecond || 
124                 		(this.second != null && this.second.equals(otherSecond)));
125         } else {
126             return false;
127         }
128     }
129     
130     @Override
131     public int hashCode() 
132     {
133     	int hashCode = 1;
134 	    hashCode = 31*hashCode + (first==null ? 0 : first.hashCode());
135 	    hashCode = 31*hashCode + (second==null ? 0 : second.hashCode());
136     	return hashCode;
137     }
138     
139     @Override
140     public String toString()
141     {
142         return "<" + first.toString() + ", " + second.toString() + ">";
143     }
144 
145     public boolean add(T o) {
146         throw new UnsupportedOperationException("Pairs cannot be mutated");
147     }
148 
149     public boolean addAll(Collection<? extends T> c) {
150         throw new UnsupportedOperationException("Pairs cannot be mutated");
151     }
152 
153     public void clear() {
154         throw new UnsupportedOperationException("Pairs cannot be mutated");
155     }
156 
157     public boolean contains(Object o) {
158         return (first == o || first.equals(o) || second == o || second.equals(o));
159     }
160 
161     public boolean containsAll(Collection<?> c) {
162         if (c.size() > 2)
163             return false;
164         Iterator<?> iter = c.iterator();
165         Object c_first = iter.next();
166         Object c_second = iter.next();
167         return this.contains(c_first) && this.contains(c_second);
168     }
169 
170     public boolean isEmpty() {
171         return false;
172     }
173 
174     public Iterator<T> iterator() {
175         return new PairIterator();
176     }
177 
178     public boolean remove(Object o) {
179         throw new UnsupportedOperationException("Pairs cannot be mutated");
180     }
181 
182     public boolean removeAll(Collection<?> c) {
183         throw new UnsupportedOperationException("Pairs cannot be mutated");
184     }
185 
186     public boolean retainAll(Collection<?> c) {
187         throw new UnsupportedOperationException("Pairs cannot be mutated");
188     }
189 
190     public int size() {
191         return 2;
192     }
193 
194     public Object[] toArray() {
195         Object[] to_return = new Object[2];
196         to_return[0] = first;
197         to_return[1] = second;
198         return to_return;
199     }
200 
201     @SuppressWarnings("unchecked")
202     public <S> S[] toArray(S[] a) {
203         S[] to_return = a;
204         Class<?> type = a.getClass().getComponentType();
205         if (a.length < 2)
206             to_return = (S[])java.lang.reflect.Array.newInstance(type, 2);
207         to_return[0] = (S)first;
208         to_return[1] = (S)second;
209         
210         if (to_return.length > 2)
211             to_return[2] = null;
212         return to_return;
213     }
214     
215     private class PairIterator implements Iterator<T>
216     {
217         int position;
218         
219         private PairIterator()
220         {
221             position = 0;
222         }
223 
224         public boolean hasNext()
225         {
226             return position < 2;
227         }
228 
229         public T next()
230         {
231             position++;
232             if (position == 1)
233                 return first;
234             else if (position == 2)
235                 return second;
236             else
237                 return null;
238         }
239 
240         public void remove()
241         {
242             throw new UnsupportedOperationException("Pairs cannot be mutated");
243         }
244     }
245 }
246 
247