1 cananian 1.1 // Tuple.java, created Sat Oct 10 01:37:39 1998 by cananian 2 cananian 1.2 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.2 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1 package harpoon.Util; 5 cananian 1.1 6 cananian 1.2.2.3 import java.util.Arrays; 7 cananian 1.2.2.3 import java.util.Collections; 8 cananian 1.2.2.6 import java.util.Comparator; 9 cananian 1.2.2.3 import java.util.List; 10 cananian 1.4 11 cananian 1.4 import net.cscott.jutil.Default; 12 cananian 1.1 /** 13 cananian 1.1 * A <code>Tuple</code> is an ordered list of objects that works 14 cananian 1.2.2.3 * properly in Hashtables & etc. Tuples may have <code>null</code> elements. 15 cananian 1.2.2.6 * <code>Tuple</code>s are <code>Comparable</code> iff the objects in 16 cananian 1.2.2.6 * the elements array are <code>Comparable</code>. 17 cananian 1.1 * 18 cananian 1.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 19 cananian 1.4 * @version $Id: Tuple.java,v 1.4 2004/02/08 01:56:15 cananian Exp $ 20 cananian 1.1 */ 21 cananian 1.2.2.9 public class Tuple implements Comparable, java.io.Serializable { 22 cananian 1.2.2.6 final Comparator objcmp; 23 cananian 1.2.2.6 final Object elements[]; 24 cananian 1.1 /** Creates a <code>Tuple</code>. */ 25 cananian 1.1 public Tuple(Object[] elements) { 26 cananian 1.1 this.elements = elements; 27 cananian 1.2.2.6 this.objcmp = Default.comparator; 28 cananian 1.1 } 29 cananian 1.2.2.6 /** Creates a <code>Comparable</code> <code>Tuple</code> which will use 30 cananian 1.2.2.6 * the specified <code>Comparator</code> to do object comparisons. */ 31 cananian 1.2.2.6 public Tuple(Object[] elements, Comparator objcmp) { 32 cananian 1.2.2.6 this.elements = elements; 33 cananian 1.2.2.6 this.objcmp = objcmp; 34 cananian 1.1 } 35 cananian 1.2.2.1 /** Projects an element of the <code>Tuple</code>. */ 36 cananian 1.2.2.1 public Object proj(int i) { return elements[i]; } 37 cananian 1.2.2.7 /** Returns an unmodifiable list view of the <code>Tuple</code>. */ 38 cananian 1.2.2.3 public List asList() { 39 cananian 1.2.2.3 return Collections.unmodifiableList(Arrays.asList(elements)); 40 cananian 1.2.2.3 } 41 cananian 1.2.2.8 /** Returns a human-readable description of this <code>Tuple</code>. */ 42 cananian 1.2.2.8 public String toString() { return Util.print(asList()); } 43 cananian 1.2.2.1 /** Synthesizes a hashcode from the hashcodes of the elements. */ 44 cananian 1.1 public int hashCode() { 45 cananian 1.1 int hc = elements.length; 46 cananian 1.1 for (int i=0; i<elements.length; i++) 47 cananian 1.2.2.3 if (elements[i]!=null) 48 cananian 1.2.2.3 hc ^= elements[i].hashCode(); 49 cananian 1.1 return hc; 50 cananian 1.1 } 51 cananian 1.2.2.1 /** Does an element-by-element comparison of two <code>Tuple</code>s. */ 52 cananian 1.1 public boolean equals(Object obj) { 53 cananian 1.2.2.4 Tuple t; 54 cananian 1.2.2.5 if (this==obj) return true; 55 cananian 1.2.2.5 if (null==obj) return false; 56 cananian 1.2.2.4 try { t = (Tuple) obj; } catch (ClassCastException e) { return false; } 57 cananian 1.1 if (this.elements.length != t.elements.length) return false; 58 cananian 1.1 for (int i=0; i<elements.length; i++) 59 cananian 1.2.2.3 if (this.elements[i]==null) { 60 cananian 1.2.2.3 if (t.elements[i]!=null) return false; 61 cananian 1.2.2.3 } else { 62 cananian 1.2.2.3 if (!this.elements[i].equals(t.elements[i])) return false; 63 cananian 1.2.2.3 } 64 cananian 1.1 return true; 65 cananian 1.2.2.6 } 66 cananian 1.2.2.6 /** Does an element-by-element comparison of two <code>Tuple</code>s. 67 cananian 1.2.2.6 * Inconsistent with <code>equals()</code> only if the underlying 68 cananian 1.2.2.6 * comparator is. Shorter tuples are compared as less than longer 69 cananian 1.2.2.6 * tuples. */ 70 cananian 1.2.2.6 public int compareTo(Object o) { // dict order: smaller first. 71 cananian 1.2.2.6 Object[] el2 = ((Tuple)o).elements; 72 cananian 1.2.2.6 if (elements.length!=el2.length) return elements.length-el2.length; 73 cananian 1.2.2.6 for (int i=0; i<elements.length; i++) { 74 cananian 1.2.2.6 int c = objcmp.compare(elements[i], el2[i]); 75 cananian 1.2.2.6 if (c!=0) return c; 76 cananian 1.2.2.6 } 77 cananian 1.2.2.6 return 0; 78 cananian 1.1 } 79 cananian 1.1 }