code: private static boolean compareUnordered(Collection col1, Collection col2, Set visited)
      {
          if (ProxyHelper.isProxyCollection(col1) || ProxyHelper.isProxyCollection(col2))
          {
              return false;
          }
  
          if (col1.size() != col2.size())
          {
              return false;
          }
  
          int h1 = deepHashCode(col1);
          int h2 = deepHashCode(col2);
          if (h1 != h2)
          { // Faster than deep equals compare (O(n^2) comparison
            // can be skipped
            // when not equal)
              return false;
          }
  
          List copy = new ArrayList(col2);
  
          for (Object element1 : col1)
          {
              int len = copy.size();
              for (int i = 0; i < len; i++)
              { // recurse here (yes, that makes
                // this a Stack-based implementation
                // with
                // partial recursion in the case of
                // unordered Sets).
                  if (deepEquals(element1, copy.get(i), visited))
                  {
                      copy.remove(i); // Shrink 2nd Set
                      break;
                  }
              }
  
              if (len == copy.size())
              { // Nothing found, therefore Collections
                // are not equivalent
                  return false;
              }
  
          }
  
          return true;
      }
docs: Deeply compare the two sets referenced by dualKey. This method attempts
  to quickly determine inequality by length, then hash, and finally does a
  deepEquals on each element if the two Sets passed by the prior tests.
  
  @param col1
  Collection one
  @param col2
  Collection two
  @param visited
  Set containing items that have already been compared, so as to
  prevent cycles.
  @return boolean true if the Sets are deeply equals, false otherwise.