Java/Class/Equals

Материал из Java эксперт
Версия от 09:36, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Compares two objects for equality, where either one or both objects may be null

   <source lang="java">

/*

* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
* 
*      http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.io.Serializable; /**

*

Operations on Object.

* 
*

This class tries to handle null input gracefully. * An exception will generally not be thrown for a null input. * Each method documents its behaviour in more detail.

*
* @author 
* @since 1.0
* @version $Id: ObjectUtils.java 594336 2007-11-12 22:54:02Z bayard $
*/

public class ObjectUtils {

   /**
*

Singleton used as a null placeholder where * null has another meaning.

    *
*

For example, in a HashMap the * {@link java.util.HashMap#get(java.lang.Object)} method returns * null if the Map contains * null or if there is no matching key. The * Null placeholder can be used to distinguish between * these two cases.

    *
*

Another example is Hashtable, where null * cannot be stored.

    *
*

This instance is Serializable.

    */
   public static final Null NULL = new Null();
   
   /**
*

ObjectUtils instances should NOT be constructed in * standard programming. Instead, the class should be used as * ObjectUtils.defaultIfNull("a","b");.

    *
*

This constructor is public to permit tools that require a JavaBean instance * to operate.

    */
   public ObjectUtils() {
       super();
   }
   // Defaulting
   //-----------------------------------------------------------------------
   /**
*

Returns a default value if the object passed is * null.

    * 
*
     * ObjectUtils.defaultIfNull(null, null)      = null
     * ObjectUtils.defaultIfNull(null, "")        = ""
     * ObjectUtils.defaultIfNull(null, "zz")      = "zz"
     * ObjectUtils.defaultIfNull("abc", *)        = "abc"
     * ObjectUtils.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
     * 
    *
    * @param object  the Object to test, may be null
    * @param defaultValue  the default value to return, may be null
    * @return object if it is not null, defaultValue otherwise
    */
   public static Object defaultIfNull(Object object, Object defaultValue) {
       return object != null ? object : defaultValue;
   }
   /**
*

Compares two objects for equality, where either one or both * objects may be null.

    *
*
     * ObjectUtils.equals(null, null)                  = true
     * ObjectUtils.equals(null, "")                    = false
     * ObjectUtils.equals("", null)                    = false
     * ObjectUtils.equals("", "")                      = true
     * ObjectUtils.equals(Boolean.TRUE, null)          = false
     * ObjectUtils.equals(Boolean.TRUE, "true")        = false
     * ObjectUtils.equals(Boolean.TRUE, Boolean.TRUE)  = true
     * ObjectUtils.equals(Boolean.TRUE, Boolean.FALSE) = false
     * 
    *
    * @param object1  the first object, may be null
    * @param object2  the second object, may be null
    * @return true if the values of both objects are the same
    */
   public static boolean equals(Object object1, Object object2) {
       if (object1 == object2) {
           return true;
       }
       if ((object1 == null) || (object2 == null)) {
           return false;
       }
       return object1.equals(object2);
   }
   /**
*

Gets the hash code of an object returning zero when the * object is null.

    *
*
     * ObjectUtils.hashCode(null)   = 0
     * ObjectUtils.hashCode(obj)    = obj.hashCode()
     * 
    *
    * @param obj  the object to obtain the hash code of, may be null
    * @return the hash code of the object, or zero if null
    * @since 2.1
    */
   public static int hashCode(Object obj) {
       return (obj == null) ? 0 : obj.hashCode();
   }
   // Identity ToString
   //-----------------------------------------------------------------------
   /**
*

Gets the toString that would be produced by Object * if a class did not override toString itself. null * will return null.

    *
*
     * ObjectUtils.identityToString(null)         = null
     * ObjectUtils.identityToString("")           = "java.lang.String@1e23"
     * ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
     * 
    *
    * @param object  the object to create a toString for, may be
    *  null
    * @return the default toString text, or null if
    *  null passed in
    */
   public static String identityToString(Object object) {
       if (object == null) {
           return null;
       }
       StringBuffer buffer = new StringBuffer();
       identityToString(buffer, object);
       return buffer.toString();
   }
   /**
*

Appends the toString that would be produced by Object * if a class did not override toString itself. null * will throw a NullPointerException for either of the two parameters.

    *
*
     * ObjectUtils.identityToString(buf, "")            = buf.append("java.lang.String@1e23"
     * ObjectUtils.identityToString(buf, Boolean.TRUE)  = buf.append("java.lang.Boolean@7fa"
     * ObjectUtils.identityToString(buf, Boolean.TRUE)  = buf.append("java.lang.Boolean@7fa")
     * 
    *
    * @param buffer  the buffer to append to
    * @param object  the object to create a toString for
    * @since 2.4
    */
   public static void identityToString(StringBuffer buffer, Object object) {
       if (object == null) {
           throw new NullPointerException("Cannot get the toString of a null identity");
       }
       buffer.append(object.getClass().getName())
             .append("@")
             .append(Integer.toHexString(System.identityHashCode(object)));
   }
   // ToString
   //-----------------------------------------------------------------------
   /**
*

Gets the toString of an Object returning * an empty string ("") if null input.

    * 
*
     * ObjectUtils.toString(null)         = ""
     * ObjectUtils.toString("")           = ""
     * ObjectUtils.toString("bat")        = "bat"
     * ObjectUtils.toString(Boolean.TRUE) = "true"
     * 
    * 
    * @see StringUtils#defaultString(String)
    * @see String#valueOf(Object)
    * @param obj  the Object to toString, may be null
    * @return the passed in Object"s toString, or nullStr if null input
    * @since 2.0
    */
   public static String toString(Object obj) {
       return obj == null ? "" : obj.toString();
   }
   /**
*

Gets the toString of an Object returning * a specified text if null input.

    * 
*
     * ObjectUtils.toString(null, null)           = null
     * ObjectUtils.toString(null, "null")         = "null"
     * ObjectUtils.toString("", "null")           = ""
     * ObjectUtils.toString("bat", "null")        = "bat"
     * ObjectUtils.toString(Boolean.TRUE, "null") = "true"
     * 
    * 
    * @see StringUtils#defaultString(String,String)
    * @see String#valueOf(Object)
    * @param obj  the Object to toString, may be null
    * @param nullStr  the String to return if null input, may be null
    * @return the passed in Object"s toString, or nullStr if null input
    * @since 2.0
    */
   public static String toString(Object obj, String nullStr) {
       return obj == null ? nullStr : obj.toString();
   }
   // Null
   //-----------------------------------------------------------------------
   /**
*

Class used as a null placeholder where null * has another meaning.

    *
*

For example, in a HashMap the * {@link java.util.HashMap#get(java.lang.Object)} method returns * null if the Map contains * null or if there is no matching key. The * Null placeholder can be used to distinguish between * these two cases.

    *
*

Another example is Hashtable, where null * cannot be stored.

    */
   public static class Null implements Serializable {
       /**
        * Required for serialization support. Declare serialization compatibility with Commons Lang 1.0
        * 
        * @see java.io.Serializable
        */
       private static final long serialVersionUID = 7092611880189329093L;
       
       /**
        * Restricted constructor - singleton.
        */
       Null() {
           super();
       }
       
       /**
*

Ensure singleton.

        * 
        * @return the singleton value
        */
       private Object readResolve() {
           return ObjectUtils.NULL;
       }
   }

}

 </source>
   
  
 
  



Equals(Equal) Method

   <source lang="java">
 

//: c03:EqualsMethod2.java // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt.

class Value {

 int i;

} public class EqualsMethod2 {

 public static void main(String[] args) {
   Value v1 = new Value();
   Value v2 = new Value();
   v1.i = v2.i = 100;
   System.out.println(v1.equals(v2));
 }

} ///:~



 </source>
   
  
 
  



Equals Method

   <source lang="java">
 

//: c03:EqualsMethod.java // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt.

public class EqualsMethod {

 public static void main(String[] args) {
   Integer n1 = new Integer(47);
   Integer n2 = new Integer(47);
   System.out.println(n1.equals(n2));
 }

} ///:~



 </source>
   
  
 
  



Equivalence

   <source lang="java">
 

//: c03:Equivalence.java // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt.

public class Equivalence {

 static Test monitor = new Test();
 public static void main(String[] args) {
   Integer n1 = new Integer(47);
   Integer n2 = new Integer(47);
   System.out.println(n1 == n2);
   System.out.println(n1 != n2);
 }

} ///:~



 </source>
   
  
 
  



Equivalence ClassSet

   <source lang="java">
   

/**

* EquivalenceClassSet.java
* 
*  @author bret5
*  Copyright(C) 2007 bret5
*  
*  This is a specialized set class which groups the elements into
*  equivalence classes based on the by the comparator provided at 
*  set creation time.  Iterators created thru the standard set interface
*  will return elements sorted by comparator order.  Elements that
*  are equivalent may be returned in any order.
*  
*  The class also provides a special loopIterator iteration 
*  which will return each element once in comparator order, then loop back
*  around to the first element at the end.  The loopIterator continues to be valid
*  as add/remove operations are performed.  If shuffleEquivalenceClasses is set,
*  it will randomly shuffles the elements in each equivalence class 
*  every time that equivalence class is reached during iteration.  If not,
*  each equivalence class will be returned in the same order every time.
*  shuffleEquivalenceClasses defaults to true.
*  
*  This Set does not allow null elements.
*  
*  This was written for a program that uses jdk 1.4, so it doesn"t yet use the generic style.  
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

import java.util.AbstractSet; import java.util.ArrayList; import java.util.ruparator; import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; /**

* @author bret5
*
*/

public class EquivalenceClassSet<T> extends AbstractSet<T> {

   // the list backing the class.  This is a list of the 
   // equivalence classes - each equivalence class is a sublist
   // which contains all the elements equivalent to each other.
   // The sublists appear in order corresponding to the ordering
   // provided by the comparator provided at set creation time. 
   private List                m_equivalenceClasses;
   private int                 m_size; // cached for efficiency
   private Comparator          m_comparator;
   private ListIterator        m_loopEqvClassIter; // non-null index used by the loop iterator
   private List                m_loopCurrentEqvClass; // ptr to current class, null ok
   private ListIterator<T>     m_loopItemIter; // non-null index used by the loop iterator
   private final static List   m_emptyList = new ArrayList(); // emptyList used for gen-ing iterators
   
   // In order to maintain some sanity in the face of objects changing with respect to
   // the comparator after being added to the set, we keep track of which class every object
   // is in.  This way, the behavior of contains and remove are undisturbed by changes to the 
   // objects.
   private HashMap         m_itemToClassMap;
   
   // TODO - size is now redundant with the size of the item-class map, remove...
   
   private int m_changeID; // supports iterator fail-fast, increment on each modification
   private boolean m_shuffleEquivalenceClasses;
   
   /*
    * Class invariants:
    *   Individual equivalence classes may not be empty
    *   The cached size is equal to the sum of all items in the sublists
    *   The changeID increments montonically whenever the set contents are changed,
    *   although it does reset on a clear()
    */
   
   public EquivalenceClassSet(Comparator<T> c) 
   {
       super();
       m_comparator = c;
       m_equivalenceClasses = new LinkedList();
       m_size = 0;
       m_itemToClassMap = new HashMap();
       resetLoopIterator();
       m_changeID = 0;
       m_shuffleEquivalenceClasses = true;
   }
   protected class OnePassIterator implements Iterator<T> 
   {
       private int localChangeID;
       private ListIterator localEqvClassIter; // class iter
       private ListIterator<T> localItemIter; // item iter
       protected OnePassIterator() 
       {
           localChangeID = m_changeID;
           localEqvClassIter = m_equivalenceClasses.listIterator(); // index used by the loop iterator
           localItemIter = null; // null means before the next class
       }
       
       public boolean hasNext() 
       {
           if (m_changeID != localChangeID) 
           {
               throw new ConcurrentModificationException();
           }
           
           if (localEqvClassIter.hasNext() || 
                   (localItemIter != null && localItemIter.hasNext())) 
           {
               return true;
           }
           
           return false;
       }
       public T next() 
       {
           if (m_changeID != localChangeID) 
           {
               throw new ConcurrentModificationException();
           }
           
           if (localItemIter == null || !localItemIter.hasNext()) 
           {
               localItemIter = ((List)localEqvClassIter.next()).listIterator();
           }
           
           return localItemIter.next();
       }
       public void remove() 
       {
           throw new UnsupportedOperationException();
       }            
   }
   
   public Iterator<T> iterator() 
   {
       return new OnePassIterator();
   }
   
   // Note that this iterator is intended to continue iteration after element addition 
   // and removal.  Therefore we put the underlying iterators in the main class so that 
   // they can be adjusted/replaced when necessary
   // invariants:
   //   if size = 0, currentEqvClassIter is null.
   //   if size not null, then both currentEqvClassIter and currentItemIter
   //     are not null.
   protected class LoopIterator implements Iterator<T> 
   {
       public boolean hasNext() 
       {
           return ( m_size > 0 );
       }
       public T next() 
       {
           assert m_loopEqvClassIter != null;
           assert m_loopItemIter != null;
           
           if (m_size <= 0) 
           {
               throw new NoSuchElementException();
           }
           
           // first, move to a new class if necessary, resetting the item iter.
           // if switching classes, shuffle.
           if (!m_loopItemIter.hasNext()) 
           {
               if (!m_loopEqvClassIter.hasNext()) 
               {
                   // recycle to beginning
                   m_loopEqvClassIter = m_equivalenceClasses.listIterator();
               }
               
               m_loopCurrentEqvClass = (List)m_loopEqvClassIter.next();
               assert m_loopCurrentEqvClass.size() > 0;
               
               if (m_shuffleEquivalenceClasses) 
               {
                   java.util.Collections.shuffle(m_loopCurrentEqvClass);
               }
               m_loopItemIter = m_loopCurrentEqvClass.listIterator();                
           }
           
           return m_loopItemIter.next();
       }
       public void remove() 
       {
           throw new UnsupportedOperationException();
       }                               
   }
   
   /**
    * The loopIterator is a special iteration for which hasNext() returns 
    * true if the size is greater than 0.  The next() method 
    * traverses the equivalence classes in comparator order.  Within
    * each equivalence class, the items are returned randomly 
    * (by shuffling the elements in the equivalence class every time 
    * that equivalence class is reached during iteration).
    * 
    * Iteration can be reset to the first equivalence class by using
    * the resetLoopIterator method of the main class.
    *   
    * @return the iterator
    */
   public Iterator<T> loopIterator() 
   {
       return new LoopIterator();
   }
  
   public void resetLoopIterator() 
   {
       m_loopEqvClassIter = m_equivalenceClasses.listIterator();
       m_loopCurrentEqvClass = null;
       m_loopItemIter = m_emptyList.listIterator();        
   }
   
   /**
    * If shuffleEquivalenceClasses is set, the loopItertor will randomly shuffle 
    * the elements in each equivalence class every time that equivalence class 
    * is reached during iteration.
    * 
    * @return the value of shuffleEquivalenceClasses
    */
   public boolean isShuffleEquivalenceClasses() 
   {
       return m_shuffleEquivalenceClasses;
   }
   /**
    * Set the value of shuffleEquivalenceClasses.
    * @see isShuffleEquivalenceClasses()
    */
   public void setShuffleEquivalenceClasses(boolean shuffleEquivalenceClasses) 
   {
       this.m_shuffleEquivalenceClasses = shuffleEquivalenceClasses;
   }
   /* (non-Javadoc)
    * @see java.util.AbstractCollection#size()
    */
   public int size() 
   {
       return m_size;
   }
   /* 
    * Adds the argument to the collection.  If the element is not already
    * a member of the set, and is equivalent to the current equivalence 
    * class, it is added so that it will be returned before any element
    * from another class is returned.
    */
   public boolean add(T arg0) 
   {
       return addPositional(arg0, true);
   }
   /* 
    * Adds the argument to the collection.  If the element is not already
    * a member of the set, and is equivalent to the current equivalence 
    * class, it is added so that it will not be returned before an element
    * from another class is returned (if there are any other classes).
    */
   public boolean addExpired(T arg0) 
   {
       return addPositional(arg0, false);
   }
   protected boolean addPositional(Object arg0, boolean atEnd) 
   {
       EqvPosition eqvPosition = findEqvClass(arg0);
       boolean isChanged = false;
       if (eqvPosition.matchingEqvClass != null) 
       {
           int iterIdx = 0;
           boolean replaceLoopItemIter = false;
           
           if (eqvPosition.matchingEqvClass == m_loopCurrentEqvClass) 
           {
               // we have to replace the item loop iterator for this class, so get the position
               replaceLoopItemIter = true;
               iterIdx = m_loopItemIter.nextIndex();
           }
           
           if (!eqvPosition.matchingEqvClass.contains(arg0)) 
           {
               if (atEnd) 
               {
                   eqvPosition.matchingEqvClass.add(arg0);
               } 
               else
               {
                   eqvPosition.matchingEqvClass.add(0, arg0);
                   iterIdx += 1;
               }
               
               isChanged = true;
               
               if (replaceLoopItemIter) 
               {
                   m_loopItemIter = m_loopCurrentEqvClass.listIterator(iterIdx);
               }
           }
       } 
       else 
       {
           // there is no matching class, so add one
           ArrayList newEqvClass = new ArrayList();
           newEqvClass.add(arg0);
           eqvPosition.matchingEqvClass = newEqvClass;  // cache the eqv class ref for adding to map
           int iterIdx, addIdx;
           iterIdx = 0;
           addIdx = 0;
           
           if (m_size >= 1) 
           {
               iterIdx = m_loopEqvClassIter.nextIndex();
               addIdx = eqvPosition.eqvClassIter.nextIndex();
               if (addIdx < iterIdx) 
               {
                   iterIdx += 1;
               }
           } 
           eqvPosition.eqvClassIter.add(newEqvClass);                
           isChanged = true;
           
           // replace the class loop iterator
           m_loopEqvClassIter = m_equivalenceClasses.listIterator(iterIdx);
           
           // if the new class is next and the add is "expired"/(not atEnd), 
           // advance the iterator past the just added item
           if (iterIdx == addIdx && !atEnd && !m_loopItemIter.hasNext()) 
           {
               m_loopCurrentEqvClass = (List)m_loopEqvClassIter.next();
               m_loopItemIter = m_loopCurrentEqvClass.listIterator(1);
           }
       }
       
       if (isChanged) 
       {
           m_size += 1;
           m_changeID += 1;
           m_itemToClassMap.put(arg0, eqvPosition.matchingEqvClass);
       }
       
       return isChanged;
   }
   // represents the location of the equivalence class matching a value.
   // returned from findEqvClass, so we only have to write that code once.
   // If there is a matching class, then matchingEqvClass will be non-null.
   // If not, then eqvClassIter holds the position that eqv class would have.
   protected class EqvPosition 
   {
       protected List matchingEqvClass;
       protected ListIterator eqvClassIter;
   }
   // If there is a matching class, then matchingEqvClass will be non-null.
   // If not, then eqvClassIter holds the position that eqv class would have.
   protected EqvPosition findEqvClass(Object arg0) 
   {
       EqvPosition eqvPosition = new EqvPosition();
       if (m_itemToClassMap.containsKey(arg0)) 
       {
           eqvPosition.matchingEqvClass = (List)m_itemToClassMap.get(arg0);
           return eqvPosition;  // note that the iterator will be null.
       }
       
       eqvPosition.eqvClassIter = m_equivalenceClasses.listIterator();
       while (eqvPosition.eqvClassIter.hasNext()) 
       {
           List testEqvClass = (List)eqvPosition.eqvClassIter.next();
           assert testEqvClass.size() > 0;
           int comparison = m_comparator.rupare(arg0, testEqvClass.get(0));
           if (comparison < 0) 
           {
               // there is no matching class, to insert before this one, return the previous position
               if (eqvPosition.eqvClassIter.hasPrevious()) 
               {
                   eqvPosition.eqvClassIter.previous();
               }
               break;
           } 
           else if (comparison == 0) 
           {
               eqvPosition.matchingEqvClass = testEqvClass;
               return eqvPosition; 
           }
           // and fall through to the next eqvClass
       }
       return eqvPosition;
   }
   
   /* (non-Javadoc)
    * @see java.util.AbstractCollection#clear()
    */
   public void clear() 
   {
       m_equivalenceClasses.clear();
       m_itemToClassMap.clear();
       m_size = 0;
       m_changeID = 0; // can reset to original state
       resetLoopIterator();
   }
   /* (non-Javadoc)
    * @see java.util.AbstractCollection#contains(java.lang.Object)
    */
   public boolean contains(Object arg0) 
   {
       EqvPosition eqvPosition = findEqvClass(arg0);
       if (eqvPosition.matchingEqvClass != null &&
               eqvPosition.matchingEqvClass.contains(arg0)) 
       {
           return true; // already a member, do nothing
       }   
       return false;
   }
   /* (non-Javadoc)
    * @see java.util.AbstractCollection#remove(java.lang.Object)
    */
   public boolean remove(Object arg0) 
   {
       assert m_size == m_itemToClassMap.size();
       EqvPosition eqvPosition = findEqvClass(arg0);
       return removeAtPosition(eqvPosition, arg0);
   }
   /* (non-Javadoc)
    * @see java.util.AbstractCollection#remove(java.lang.Object)
    */
   private boolean removeAtPosition(EqvPosition eqvPosition, Object arg0) 
   {
       // when removing an object, we may have to replace the item loop iterator
       // if we removed an item from the current loop class
       // also, if the removal results in removal of a class, we may have to 
       // replace the class loop iter 
       boolean isChanged = false;
       boolean replaceLoopItemIter = false;
       if (eqvPosition.matchingEqvClass != null) 
       {
           int itemLocationIdx = 0;
           int loopNextItemIdx = 0;
           int itemClassIdx = 0;
           int loopNextClassIdx = 0;
           itemLocationIdx = eqvPosition.matchingEqvClass.indexOf(arg0);
           if (itemLocationIdx >= 0) 
           {
               // the item is a member of this class and will be removed 
               isChanged = true; 
               if (eqvPosition.matchingEqvClass == m_loopCurrentEqvClass) 
               {
                   // we may have to replace the item loop iterator for this class, so get the position
                   replaceLoopItemIter = true;
                   loopNextItemIdx = m_loopItemIter.nextIndex();
                   if (itemLocationIdx < loopNextItemIdx) 
                   {
                       loopNextItemIdx -= 1;
                   }
               }
               eqvPosition.matchingEqvClass.remove(arg0);
               if (eqvPosition.matchingEqvClass.size() <= 0) 
               {
                   // the class is now empty, remove it
                   loopNextClassIdx = m_loopEqvClassIter.nextIndex();
                   itemClassIdx = m_equivalenceClasses.indexOf(eqvPosition.matchingEqvClass);
                   if (itemClassIdx < loopNextClassIdx) 
                   {
                       loopNextClassIdx -= 1;
                   }
                   
                   m_equivalenceClasses.remove(eqvPosition.matchingEqvClass);
                   
                   // and replace the loop iterator, and maybe the item iterator 
                   if (m_equivalenceClasses.size() == 0) 
                   {
                       resetLoopIterator();
                   } 
                   else 
                   {                        
                       m_loopEqvClassIter = m_equivalenceClasses.listIterator(loopNextClassIdx);
                       if (eqvPosition.matchingEqvClass == m_loopCurrentEqvClass) 
                       {
                           m_loopCurrentEqvClass = null;
                           m_loopItemIter = m_emptyList.listIterator(); 
                       }                        
                   }
               } 
               else if (replaceLoopItemIter) 
               {
                   // replace the item iterator for the class
                   m_loopItemIter = m_loopCurrentEqvClass.listIterator(loopNextItemIdx); 
               }   
           }
       }
       
       if (isChanged) 
       {
           m_itemToClassMap.remove(arg0);
           m_size -= 1;
           assert m_size >= 0;
           assert m_size == m_itemToClassMap.size();
           m_changeID += 1;
       }
       
       return isChanged;
   }
   
   public Comparator<T> getComparator() 
   {
       return m_comparator;
   }
   
   /**
    * Partition this set into two sets, returning the new one.
    * 
    * The argument specifies how many elements to put in the new set.  Elements will be 
    * chosen in comparator order.  All elements put into the new set will be removed from 
    * this set.  If the original set contained less elements than the argument, then
    * after the partition the new set will contain all the elements and the original set
    * will be empty.
    *  
    * If the partition is non-trivial (that is, if the new set contains at least one 
    * element), then the counters for the loop iterator will be reset.
    *  
    * @param numberToRemove number of elements to remove from the original set
    * 
    * @return the new set
    */
   public EquivalenceClassSet<T> partition(int numberToRemove) 
   {
       EquivalenceClassSet<T> newSet = new EquivalenceClassSet<T>(m_comparator);
       while (numberToRemove > 0 && m_size > 0) 
       {
           ArrayList firstEqvClass = (ArrayList)(m_equivalenceClasses.get(0));
           int sizeOfFEqvClass = firstEqvClass.size();
           int numberMoved = 0;
           List movedEqvClass;
           if (numberToRemove >= sizeOfFEqvClass) 
           {
               movedEqvClass = (List)m_equivalenceClasses.remove(0);
               newSet.m_equivalenceClasses.add(movedEqvClass);
               numberMoved = sizeOfFEqvClass;
               
           } 
           else 
           {
               // shuffle the equivalence class prior to a partial selection
               if (m_shuffleEquivalenceClasses) 
               {
                   java.util.Collections.shuffle(firstEqvClass);
               }
               
               movedEqvClass = new ArrayList(firstEqvClass.subList(0, numberToRemove));
               firstEqvClass.subList(0, numberToRemove).clear();
               newSet.m_equivalenceClasses.add(movedEqvClass);
               numberMoved = numberToRemove;
           }
           
           m_size -= numberMoved;
           newSet.m_size += numberMoved;
           numberToRemove -= numberMoved;
           
           // now fix up the item to class map
           Iterator iter = movedEqvClass.iterator();
           while (iter.hasNext()) 
           {
               Object obj = iter.next();
               m_itemToClassMap.remove(obj);                
               newSet.m_itemToClassMap.put(obj, movedEqvClass);                
           }
       }
       
       if (newSet.size() > 0) 
       {
           newSet.resetLoopIterator();
           resetLoopIterator();
           m_changeID += 1;
           newSet.m_changeID += 1;
       }
       assert m_size == m_itemToClassMap.size(); 
       assert newSet.m_size == newSet.m_itemToClassMap.size(); 
       return newSet;
   }
   
   /**
    * In some cases, the equivalence class of an object will change.  This can leave
    * the list in an inconsistent state.  It is essential to fix the problem. 
    * This method moves the object to the correct equivalence class, keeping the 
    * loopIterator where it was.
    * 
    * @param arg0 The object to move.
    * @return true if the object is a member of the set, false otherwise.
    */
   public boolean resetEquivalenceClass(T arg0) 
   {
       boolean found = false;
       EqvPosition eqvPosition = new EqvPosition();
       eqvPosition.matchingEqvClass = (List)m_itemToClassMap.get(arg0);
       
       if (eqvPosition.matchingEqvClass != null) 
       {
           removeAtPosition(eqvPosition, arg0);
           found = true;
       }
       
       if (found) 
       {
           addExpired(arg0);
       }
       
       return found;
   }

}



 </source>
   
  
 
  



If the given objects are equal

   <source lang="java">
   

import java.lang.reflect.Array; import java.util.Arrays; /*

* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

//Revised from springframework /**

* Miscellaneous object utility methods. Mainly for internal use within the
* framework; consider Jakarta"s Commons Lang for a more comprehensive suite
* of object utilities.
*
* @author Juergen Hoeller
* @author Keith Donald
* @author Rod Johnson
* @author Rob Harrop
* @author Alex Ruiz
* @since 19.03.2004
* @see org.apache.rumons.lang.ObjectUtils
*/

abstract class ObjectUtils {

 private static final int INITIAL_HASH = 7;
 private static final int MULTIPLIER = 31;
 private static final String EMPTY_STRING = "";
 private static final String NULL_STRING = "null";
 private static final String ARRAY_START = "{";
 private static final String ARRAY_END = "}";
 private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;
 private static final String ARRAY_ELEMENT_SEPARATOR = ", ";
 /**
  * Determine if the given objects are equal, returning true
  * if both are null or false if only one is
  * null.
*

Compares arrays with Arrays.equals, performing an equality * check based on the array elements rather than the array reference. * @param o1 first Object to compare * @param o2 second Object to compare * @return whether the given objects are equal * @see java.util.Arrays#equals */ public static boolean nullSafeEquals(Object o1, Object o2) { if (o1 == o2) { return true; } if (o1 == null || o2 == null) { return false; } if (o1.equals(o2)) { return true; } if (o1 instanceof Object[] && o2 instanceof Object[]) { return Arrays.equals((Object[]) o1, (Object[]) o2); } if (o1 instanceof boolean[] && o2 instanceof boolean[]) { return Arrays.equals((boolean[]) o1, (boolean[]) o2); } if (o1 instanceof byte[] && o2 instanceof byte[]) { return Arrays.equals((byte[]) o1, (byte[]) o2); } if (o1 instanceof char[] && o2 instanceof char[]) { return Arrays.equals((char[]) o1, (char[]) o2); } if (o1 instanceof double[] && o2 instanceof double[]) { return Arrays.equals((double[]) o1, (double[]) o2); } if (o1 instanceof float[] && o2 instanceof float[]) { return Arrays.equals((float[]) o1, (float[]) o2); } if (o1 instanceof int[] && o2 instanceof int[]) { return Arrays.equals((int[]) o1, (int[]) o2); } if (o1 instanceof long[] && o2 instanceof long[]) { return Arrays.equals((long[]) o1, (long[]) o2); } if (o1 instanceof short[] && o2 instanceof short[]) { return Arrays.equals((short[]) o1, (short[]) o2); } return false; } } </source>

Test the equality of two object arrays

   <source lang="java">

import java.lang.reflect.Array; /*

* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

public class Main {

 /**
  * Test the equality of two object arrays.
  *
  * @param a       The first array.
  * @param b       The second array.
  * @param deep    True to traverse elements which are arrays.
  * @return        True if arrays are equal.
  */
 public static boolean equals(final Object[] a, final Object[] b,
                              final boolean deep)
 {
    if (a == b) return true;
    if (a == null || b == null) return false;
    if (a.length != b.length) return false;
    for (int i=0; i<a.length; i++) {
       Object x = a[i];
       Object y = b[i];
       if (x != y) return false;
       if (x == null || y == null) return false;
       if (deep) {
          if (x instanceof Object[] && y instanceof Object[]) {
             if (! equals((Object[])x, (Object[])y, true)) return false;
          }
          else {
             return false;
          }
       }
       if (! x.equals(y)) return false;
    }
    return true;
 }
 /**
  * Test the equality of two object arrays.
  *
  * @param a    The first array.
  * @param b    The second array.
  * @return     True if arrays are equal.
  */
 public static boolean equals(final Object[] a, final Object[] b) {
    return equals(a, b, true);
 }

}

 </source>