001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.collections.comparators; 018 019 import java.io.Serializable; 020 import java.util.Comparator; 021 022 /** 023 * A Comparator that will compare nulls to be either lower or higher than 024 * other objects. 025 * 026 * @since Commons Collections 2.0 027 * @version $Revision: 647116 $ $Date: 2008-04-11 12:23:08 +0100 (Fri, 11 Apr 2008) $ 028 * 029 * @author Michael A. Smith 030 */ 031 public class NullComparator implements Comparator, Serializable { 032 033 /** Serialization version. */ 034 private static final long serialVersionUID = -5820772575483504339L; 035 036 /** 037 * The comparator to use when comparing two non-<code>null</code> objects. 038 **/ 039 private Comparator nonNullComparator; 040 041 /** 042 * Specifies whether a <code>null</code> are compared as higher than 043 * non-<code>null</code> objects. 044 **/ 045 private boolean nullsAreHigh; 046 047 //----------------------------------------------------------------------- 048 /** 049 * Construct an instance that sorts <code>null</code> higher than any 050 * non-<code>null</code> object it is compared with. When comparing two 051 * non-<code>null</code> objects, the {@link ComparableComparator} is 052 * used. 053 **/ 054 public NullComparator() { 055 this(ComparableComparator.getInstance(), true); 056 } 057 058 /** 059 * Construct an instance that sorts <code>null</code> higher than any 060 * non-<code>null</code> object it is compared with. When comparing two 061 * non-<code>null</code> objects, the specified {@link Comparator} is 062 * used. 063 * 064 * @param nonNullComparator the comparator to use when comparing two 065 * non-<code>null</code> objects. This argument cannot be 066 * <code>null</code> 067 * 068 * @exception NullPointerException if <code>nonNullComparator</code> is 069 * <code>null</code> 070 **/ 071 public NullComparator(Comparator nonNullComparator) { 072 this(nonNullComparator, true); 073 } 074 075 /** 076 * Construct an instance that sorts <code>null</code> higher or lower than 077 * any non-<code>null</code> object it is compared with. When comparing 078 * two non-<code>null</code> objects, the {@link ComparableComparator} is 079 * used. 080 * 081 * @param nullsAreHigh a <code>true</code> value indicates that 082 * <code>null</code> should be compared as higher than a 083 * non-<code>null</code> object. A <code>false</code> value indicates 084 * that <code>null</code> should be compared as lower than a 085 * non-<code>null</code> object. 086 **/ 087 public NullComparator(boolean nullsAreHigh) { 088 this(ComparableComparator.getInstance(), nullsAreHigh); 089 } 090 091 /** 092 * Construct an instance that sorts <code>null</code> higher or lower than 093 * any non-<code>null</code> object it is compared with. When comparing 094 * two non-<code>null</code> objects, the specified {@link Comparator} is 095 * used. 096 * 097 * @param nonNullComparator the comparator to use when comparing two 098 * non-<code>null</code> objects. This argument cannot be 099 * <code>null</code> 100 * 101 * @param nullsAreHigh a <code>true</code> value indicates that 102 * <code>null</code> should be compared as higher than a 103 * non-<code>null</code> object. A <code>false</code> value indicates 104 * that <code>null</code> should be compared as lower than a 105 * non-<code>null</code> object. 106 * 107 * @exception NullPointerException if <code>nonNullComparator</code> is 108 * <code>null</code> 109 **/ 110 public NullComparator(Comparator nonNullComparator, boolean nullsAreHigh) { 111 this.nonNullComparator = nonNullComparator; 112 this.nullsAreHigh = nullsAreHigh; 113 114 if(nonNullComparator == null) { 115 throw new NullPointerException("null nonNullComparator"); 116 } 117 } 118 119 //----------------------------------------------------------------------- 120 /** 121 * Perform a comparison between two objects. If both objects are 122 * <code>null</code>, a <code>0</code> value is returned. If one object 123 * is <code>null</code> and the other is not, the result is determined on 124 * whether the Comparator was constructed to have nulls as higher or lower 125 * than other objects. If neither object is <code>null</code>, an 126 * underlying comparator specified in the constructor (or the default) is 127 * used to compare the non-<code>null</code> objects. 128 * 129 * @param o1 the first object to compare 130 * @param o2 the object to compare it to. 131 * @return <code>-1</code> if <code>o1</code> is "lower" than (less than, 132 * before, etc.) <code>o2</code>; <code>1</code> if <code>o1</code> is 133 * "higher" than (greater than, after, etc.) <code>o2</code>; or 134 * <code>0</code> if <code>o1</code> and <code>o2</code> are equal. 135 **/ 136 public int compare(Object o1, Object o2) { 137 if(o1 == o2) { return 0; } 138 if(o1 == null) { return (this.nullsAreHigh ? 1 : -1); } 139 if(o2 == null) { return (this.nullsAreHigh ? -1 : 1); } 140 return this.nonNullComparator.compare(o1, o2); 141 } 142 143 //----------------------------------------------------------------------- 144 /** 145 * Implement a hash code for this comparator that is consistent with 146 * {@link #equals(Object)}. 147 * 148 * @return a hash code for this comparator. 149 **/ 150 public int hashCode() { 151 return (nullsAreHigh ? -1 : 1) * nonNullComparator.hashCode(); 152 } 153 154 /** 155 * Determines whether the specified object represents a comparator that is 156 * equal to this comparator. 157 * 158 * @param obj the object to compare this comparator with. 159 * 160 * @return <code>true</code> if the specified object is a NullComparator 161 * with equivalent <code>null</code> comparison behavior 162 * (i.e. <code>null</code> high or low) and with equivalent underlying 163 * non-<code>null</code> object comparators. 164 **/ 165 public boolean equals(Object obj) { 166 if(obj == null) { return false; } 167 if(obj == this) { return true; } 168 if(!obj.getClass().equals(this.getClass())) { return false; } 169 170 NullComparator other = (NullComparator)obj; 171 172 return ((this.nullsAreHigh == other.nullsAreHigh) && 173 (this.nonNullComparator.equals(other.nonNullComparator))); 174 } 175 176 }