View Javadoc
1   /*
2    * Created on Apr 2, 2006
3    *
4    * Copyright (c) 2006, The JUNG Authors 
5    *
6    * All rights reserved.
7    *
8    * This software is open-source under the BSD license; see either
9    * "license.txt" or
10   * https://github.com/jrtom/jung/blob/master/LICENSE 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       * 
75       * @param values the values to be used to construct this Pair
76       * @throws IllegalArgumentException if the input array is null,
77       * contains null values, or has != 2 elements.
78       */
79      public Pair(T[] values)
80      {
81          if (values == null)
82              throw new IllegalArgumentException("Input array cannot be null");
83          if (values.length == 2)
84          {
85              if(values[0] == null || values[1] == null) 
86                  throw new IllegalArgumentException("Pair cannot contain null values");
87              first = values[0];
88              second = values[1];
89          }
90          else
91              throw new IllegalArgumentException("Pair may only be created from an " +
92              		"array of 2 elements");
93      }
94  
95      /**
96       * @return the first element.
97       */
98      public T getFirst() 
99      {
100         return first;
101     }
102     
103     /**
104      * @return the second element.
105      */
106     public T getSecond() 
107     {
108         return second;
109     }
110     
111     @Override
112     public boolean equals( Object o ) {
113         if (o == this)
114             return true;
115 
116         if (o instanceof Pair) {
117             @SuppressWarnings("rawtypes")
118 			Pair otherPair = (Pair) o;
119             Object otherFirst = otherPair.getFirst();
120             Object otherSecond = otherPair.getSecond();
121             return 
122             	(this.first  == otherFirst  || 
123             			(this.first != null  && this.first.equals(otherFirst)))   
124             			&&
125                 (this.second == otherSecond || 
126                 		(this.second != null && this.second.equals(otherSecond)));
127         } else {
128             return false;
129         }
130     }
131     
132     @Override
133     public int hashCode() 
134     {
135     	int hashCode = 1;
136 	    hashCode = 31*hashCode + (first==null ? 0 : first.hashCode());
137 	    hashCode = 31*hashCode + (second==null ? 0 : second.hashCode());
138     	return hashCode;
139     }
140     
141     @Override
142     public String toString()
143     {
144         return "<" + first.toString() + ", " + second.toString() + ">";
145     }
146 
147     public boolean add(T o) {
148         throw new UnsupportedOperationException("Pairs cannot be mutated");
149     }
150 
151     public boolean addAll(Collection<? extends T> c) {
152         throw new UnsupportedOperationException("Pairs cannot be mutated");
153     }
154 
155     public void clear() {
156         throw new UnsupportedOperationException("Pairs cannot be mutated");
157     }
158 
159     public boolean contains(Object o) {
160         return (first == o || first.equals(o) || second == o || second.equals(o));
161     }
162 
163     public boolean containsAll(Collection<?> c) {
164         if (c.size() > 2)
165             return false;
166         Iterator<?> iter = c.iterator();
167         Object c_first = iter.next();
168         Object c_second = iter.next();
169         return this.contains(c_first) && this.contains(c_second);
170     }
171 
172     public boolean isEmpty() {
173         return false;
174     }
175 
176     public Iterator<T> iterator() {
177         return new PairIterator();
178     }
179 
180     public boolean remove(Object o) {
181         throw new UnsupportedOperationException("Pairs cannot be mutated");
182     }
183 
184     public boolean removeAll(Collection<?> c) {
185         throw new UnsupportedOperationException("Pairs cannot be mutated");
186     }
187 
188     public boolean retainAll(Collection<?> c) {
189         throw new UnsupportedOperationException("Pairs cannot be mutated");
190     }
191 
192     public int size() {
193         return 2;
194     }
195 
196     public Object[] toArray() {
197         Object[] to_return = new Object[2];
198         to_return[0] = first;
199         to_return[1] = second;
200         return to_return;
201     }
202 
203     @SuppressWarnings("unchecked")
204     public <S> S[] toArray(S[] a) {
205         S[] to_return = a;
206         Class<?> type = a.getClass().getComponentType();
207         if (a.length < 2)
208             to_return = (S[])java.lang.reflect.Array.newInstance(type, 2);
209         to_return[0] = (S)first;
210         to_return[1] = (S)second;
211         
212         if (to_return.length > 2)
213             to_return[2] = null;
214         return to_return;
215     }
216     
217     private class PairIterator implements Iterator<T>
218     {
219         int position;
220         
221         private PairIterator()
222         {
223             position = 0;
224         }
225 
226         public boolean hasNext()
227         {
228             return position < 2;
229         }
230 
231         public T next()
232         {
233             position++;
234             if (position == 1)
235                 return first;
236             else if (position == 2)
237                 return second;
238             else
239                 return null;
240         }
241 
242         public void remove()
243         {
244             throw new UnsupportedOperationException("Pairs cannot be mutated");
245         }
246     }
247 }
248 
249