001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2007-2012 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.util; 011 012import mondrian.olap.Util; 013 014import java.util.*; 015 016/** 017 * Pair of values. 018 * 019 * <p>Because a pair implements {@link #equals(Object)}, {@link #hashCode()} and 020 * {@link #compareTo(Pair)}, it can be used in any kind of 021 * {@link java.util.Collection}. 022 * 023 * @author jhyde 024 * @since Apr 19, 2007 025 */ 026public class Pair <L, R> 027 implements Comparable<Pair<L, R>>, Map.Entry<L, R> 028{ 029 public L left; 030 public R right; 031 032 /** 033 * Creates a pair. 034 * 035 * @param left Left value 036 * @param right Right value 037 */ 038 public Pair(L left, R right) { 039 this.left = left; 040 this.right = right; 041 } 042 043 /** 044 * Creates a pair representing the same mapping as the 045 * specified entry. 046 * 047 * @param entry the entry to copy 048 */ 049 public Pair(Map.Entry<? extends L, ? extends R> entry) { 050 this.left = entry.getKey(); 051 this.right = entry.getValue(); 052 } 053 054 /** 055 * Creates a Pair. 056 * 057 * @param left Left value 058 * @param right Right value 059 * @return a new Pair 060 */ 061 public static <L, R> Pair<L, R> of(L left, R right) { 062 return new Pair<L, R>(left, right); 063 } 064 065 public boolean equals(Object obj) { 066 if (obj instanceof Pair) { 067 //noinspection unchecked 068 Pair<L, R> pair = (Pair) obj; 069 return Util.equals(this.left, pair.left) 070 && Util.equals(this.right, pair.right); 071 } 072 return false; 073 } 074 075 public int hashCode() { 076 int k = (left == null) ? 0 : left.hashCode(); 077 int k1 = (right == null) ? 0 : right.hashCode(); 078 return ((k << 4) | k) ^ k1; 079 } 080 081 082 public int compareTo(Pair<L, R> that) { 083 int c = compare((Comparable) this.left, (Comparable)that.left); 084 if (c == 0) { 085 c = compare((Comparable) this.right, (Comparable)that.right); 086 } 087 return c; 088 } 089 090 public String toString() { 091 return "<" + left + ", " + right + ">"; 092 } 093 094 // implement Map.Entry 095 public L getKey() { 096 return left; 097 } 098 099 // implement Map.Entry 100 public R getValue() { 101 return right; 102 } 103 104 // implement Map.Entry 105 public R setValue(R value) { 106 R previous = right; 107 right = value; 108 return previous; 109 } 110 111 /** 112 * Compares a pair of comparable values of the same type. Null collates 113 * less than everything else, but equal to itself. 114 * 115 * @param c1 First value 116 * @param c2 Second value 117 * @return a negative integer, zero, or a positive integer if c1 118 * is less than, equal to, or greater than c2. 119 */ 120 private static <C extends Comparable<C>> int compare(C c1, C c2) { 121 if (c1 == null) { 122 if (c2 == null) { 123 return 0; 124 } else { 125 return -1; 126 } 127 } else if (c2 == null) { 128 return 1; 129 } else { 130 return c1.compareTo(c2); 131 } 132 } 133 134 /** 135 * Returns an iterable over the left slice of an iterable. 136 * 137 * @param iterable Iterable over pairs 138 * @param <L> Left type 139 * @param <R> Right type 140 * @return Iterable over the left elements 141 */ 142 public static <L, R> Iterable<L> leftIter( 143 final Iterable<Pair<L, R>> iterable) 144 { 145 return new Iterable<L>() { 146 public Iterator<L> iterator() { 147 final Iterator<Pair<L, R>> iterator = iterable.iterator(); 148 return new Iterator<L>() { 149 public boolean hasNext() { 150 return iterator.hasNext(); 151 } 152 153 public L next() { 154 return iterator.next().left; 155 } 156 157 public void remove() { 158 iterator.remove(); 159 } 160 }; 161 } 162 }; 163 } 164 165 /** 166 * Returns an iterable over the right slice of an iterable. 167 * 168 * @param iterable Iterable over pairs 169 * @param <L> right type 170 * @param <R> Right type 171 * @return Iterable over the right elements 172 */ 173 public static <L, R> Iterable<R> rightIter( 174 final Iterable<Pair<L, R>> iterable) 175 { 176 return new Iterable<R>() { 177 public Iterator<R> iterator() { 178 final Iterator<Pair<L, R>> iterator = iterable.iterator(); 179 return new Iterator<R>() { 180 public boolean hasNext() { 181 return iterator.hasNext(); 182 } 183 184 public R next() { 185 return iterator.next().right; 186 } 187 188 public void remove() { 189 iterator.remove(); 190 } 191 }; 192 } 193 }; 194 } 195 196 /** 197 * Returns a list of the left elements of a list of pairs. 198 */ 199 public static <L, R> List<L> left(final List<Pair<L, R>> list) { 200 return new AbstractList<L>() { 201 public L get(int index) { 202 return list.get(index).left; 203 } 204 205 public int size() { 206 return list.size(); 207 } 208 209 public L remove(int index) { 210 Pair<L, R> pair = list.remove(index); 211 return pair == null ? null : pair.left; 212 } 213 }; 214 } 215 216 /** 217 * Returns a list of the right elements of a list of pairs. 218 */ 219 public static <L, R> List<R> right(final List<Pair<L, R>> list) { 220 return new AbstractList<R>() { 221 public R get(int index) { 222 return list.get(index).right; 223 } 224 225 public int size() { 226 return list.size(); 227 } 228 229 public R remove(int index) { 230 Pair<L, R> pair = list.remove(index); 231 return pair == null ? null : pair.right; 232 } 233 }; 234 } 235} 236 237// End Pair.java