@Override
  public int compareTo(Path other) {
    if (!(other instanceof GcsPath)) {
      throw new ClassCastException();
    }

    GcsPath path = (GcsPath) other;
    int b = bucket.compareTo(path.bucket);
    if (b != 0) {
      return b;
    }

    // Compare a component at a time, so that the separator char doesn't
    // get compared against component contents.  Eg, "a/b" < "a-1/b".
    Iterator<Path> left = iterator();
    Iterator<Path> right = path.iterator();

    while (left.hasNext() && right.hasNext()) {
      String leftStr = left.next().toString();
      String rightStr = right.next().toString();
      int c = leftStr.compareTo(rightStr);
      if (c != 0) {
        return c;
      }
    }

    if (!left.hasNext() && !right.hasNext()) {
      return 0;
    } else {
      return left.hasNext() ? 1 : -1;
    }
  }
@Test
  public void testCompareTo() {
    GcsPath a = GcsPath.fromComponents("bucket", "a");
    GcsPath b = GcsPath.fromComponents("bucket", "b");
    GcsPath b2 = GcsPath.fromComponents("bucket2", "b");
    GcsPath brel = GcsPath.fromComponents(null, "b");
    GcsPath a2 = GcsPath.fromComponents("bucket", "a");
    GcsPath arel = GcsPath.fromComponents(null, "a");

    assertThat(a.compareTo(b), Matchers.lessThan(0));
    assertThat(b.compareTo(a), Matchers.greaterThan(0));
    assertThat(a.compareTo(a2), Matchers.equalTo(0));

    assertThat(a.hashCode(), Matchers.equalTo(a2.hashCode()));
    assertThat(a.hashCode(), Matchers.not(Matchers.equalTo(b.hashCode())));
    assertThat(b.hashCode(), Matchers.not(Matchers.equalTo(brel.hashCode())));

    assertThat(brel.compareTo(b), Matchers.lessThan(0));
    assertThat(b.compareTo(brel), Matchers.greaterThan(0));
    assertThat(arel.compareTo(brel), Matchers.lessThan(0));
    assertThat(brel.compareTo(arel), Matchers.greaterThan(0));

    assertThat(b.compareTo(b2), Matchers.lessThan(0));
    assertThat(b2.compareTo(b), Matchers.greaterThan(0));
  }