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 */ 017package org.apache.commons.collections4.comparators; 018 019import java.io.Serializable; 020import java.util.Comparator; 021 022import org.apache.commons.collections4.ComparatorUtils; 023 024/** 025 * A Comparator that will compare nulls to be either lower or higher than 026 * other objects. 027 * 028 * @since 2.0 029 * @version $Id: NullComparator.html 972421 2015-11-14 20:00:04Z tn $ 030 */ 031public class NullComparator<E> implements Comparator<E>, 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 final Comparator<? super E> nonNullComparator; 040 041 /** 042 * Specifies whether a <code>null</code> are compared as higher than 043 * non-<code>null</code> objects. 044 **/ 045 private final 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 @SuppressWarnings("unchecked") 055 public NullComparator() { 056 this(ComparatorUtils.NATURAL_COMPARATOR, true); 057 } 058 059 /** 060 * Construct an instance that sorts <code>null</code> higher than any 061 * non-<code>null</code> object it is compared with. When comparing two 062 * non-<code>null</code> objects, the specified {@link Comparator} is 063 * used. 064 * 065 * @param nonNullComparator the comparator to use when comparing two 066 * non-<code>null</code> objects. This argument cannot be 067 * <code>null</code> 068 * 069 * @exception NullPointerException if <code>nonNullComparator</code> is 070 * <code>null</code> 071 **/ 072 public NullComparator(final Comparator<? super E> nonNullComparator) { 073 this(nonNullComparator, true); 074 } 075 076 /** 077 * Construct an instance that sorts <code>null</code> higher or lower than 078 * any non-<code>null</code> object it is compared with. When comparing 079 * two non-<code>null</code> objects, the {@link ComparableComparator} is 080 * used. 081 * 082 * @param nullsAreHigh a <code>true</code> value indicates that 083 * <code>null</code> should be compared as higher than a 084 * non-<code>null</code> object. A <code>false</code> value indicates 085 * that <code>null</code> should be compared as lower than a 086 * non-<code>null</code> object. 087 **/ 088 @SuppressWarnings("unchecked") 089 public NullComparator(final boolean nullsAreHigh) { 090 this(ComparatorUtils.NATURAL_COMPARATOR, nullsAreHigh); 091 } 092 093 /** 094 * Construct an instance that sorts <code>null</code> higher or lower than 095 * any non-<code>null</code> object it is compared with. When comparing 096 * two non-<code>null</code> objects, the specified {@link Comparator} is 097 * used. 098 * 099 * @param nonNullComparator the comparator to use when comparing two 100 * non-<code>null</code> objects. This argument cannot be 101 * <code>null</code> 102 * 103 * @param nullsAreHigh a <code>true</code> value indicates that 104 * <code>null</code> should be compared as higher than a 105 * non-<code>null</code> object. A <code>false</code> value indicates 106 * that <code>null</code> should be compared as lower than a 107 * non-<code>null</code> object. 108 * 109 * @exception NullPointerException if <code>nonNullComparator</code> is 110 * <code>null</code> 111 **/ 112 public NullComparator(final Comparator<? super E> nonNullComparator, final boolean nullsAreHigh) { 113 this.nonNullComparator = nonNullComparator; 114 this.nullsAreHigh = nullsAreHigh; 115 116 if (nonNullComparator == null) { 117 throw new NullPointerException("null nonNullComparator"); 118 } 119 } 120 121 //----------------------------------------------------------------------- 122 /** 123 * Perform a comparison between two objects. If both objects are 124 * <code>null</code>, a <code>0</code> value is returned. If one object 125 * is <code>null</code> and the other is not, the result is determined on 126 * whether the Comparator was constructed to have nulls as higher or lower 127 * than other objects. If neither object is <code>null</code>, an 128 * underlying comparator specified in the constructor (or the default) is 129 * used to compare the non-<code>null</code> objects. 130 * 131 * @param o1 the first object to compare 132 * @param o2 the object to compare it to. 133 * @return <code>-1</code> if <code>o1</code> is "lower" than (less than, 134 * before, etc.) <code>o2</code>; <code>1</code> if <code>o1</code> is 135 * "higher" than (greater than, after, etc.) <code>o2</code>; or 136 * <code>0</code> if <code>o1</code> and <code>o2</code> are equal. 137 **/ 138 public int compare(final E o1, final E o2) { 139 if(o1 == o2) { return 0; } 140 if(o1 == null) { return this.nullsAreHigh ? 1 : -1; } 141 if(o2 == null) { return this.nullsAreHigh ? -1 : 1; } 142 return this.nonNullComparator.compare(o1, o2); 143 } 144 145 //----------------------------------------------------------------------- 146 /** 147 * Implement a hash code for this comparator that is consistent with 148 * {@link #equals(Object)}. 149 * 150 * @return a hash code for this comparator. 151 **/ 152 @Override 153 public int hashCode() { 154 return (nullsAreHigh ? -1 : 1) * nonNullComparator.hashCode(); 155 } 156 157 /** 158 * Determines whether the specified object represents a comparator that is 159 * equal to this comparator. 160 * 161 * @param obj the object to compare this comparator with. 162 * 163 * @return <code>true</code> if the specified object is a NullComparator 164 * with equivalent <code>null</code> comparison behavior 165 * (i.e. <code>null</code> high or low) and with equivalent underlying 166 * non-<code>null</code> object comparators. 167 **/ 168 @Override 169 public boolean equals(final Object obj) { 170 if(obj == null) { return false; } 171 if(obj == this) { return true; } 172 if(!obj.getClass().equals(this.getClass())) { return false; } 173 174 final NullComparator<?> other = (NullComparator<?>) obj; 175 176 return this.nullsAreHigh == other.nullsAreHigh && 177 this.nonNullComparator.equals(other.nonNullComparator); 178 } 179 180}