Closed GoogleCodeExporter closed 9 years ago
edit:
because right now, com.google.common.collect.ExplicitOrdering.rank(T)
throws IncomparableValueException when the T value is UNknown
Original comment by amer...@gmail.com
on 24 Feb 2010 at 3:49
EDIT : when the T value is UNKNOWN
Original comment by amer...@gmail.com
on 24 Feb 2010 at 3:51
On the a-b1-b2-c case, can you provide a more full illustration of what you're
really doing, so we can think
about whether there's another way to do it? I'm not sure that adding a complex
new overload to support this
case would pay for itself in the API.
On handling unknown values, I think there's a chain of orderings you can use to
accomplish this:
Ordering.explicit(...).nullsFirst().onResultOf(UNKNOWN_TO_NULL_FUNCTION);
It's not very compact, but if this is not a very common operation, that's fine.
Original comment by kevinb@google.com
on 27 Apr 2010 at 2:45
The way to handle unknown values is fine. It's a nice thought I should had.
It would be great to let extends-able package final class
com.google.common.collect.ExplicitOrdering to simplify customization.
About the a-b1-b2-c case, it happened because we used enum to describe some
business
data type.
Let's take an example :
we have enum RABBIT_TYPE { WHITE_RABBIT, SMALL_RABBIT, GRAY_RABBIT, BIG_RABBIT}.
The categorization is wrong among this type because we mixed different kind of
physical attribute (color and height) but we cannot change that easily.
So, for us, color attribute are equals and height attribute are equals but they
all
are of the same enum type. Maybe we could create RABBIT_COLOR_TYPE and so on,
but java
don't let extends enum and we are stuck with all legacy code that use these
enum type.
So we'd like to use Ordering.explicit([WHITE_RABBIT, GRAY_RABBIT],
[SMALL_RABBIT,
BIG_RABBIT])
Hope it helps.
Original comment by amer...@gmail.com
on 27 Apr 2010 at 3:49
There are two independent issues here; handling unknowns, and handling equality.
For equality, I agree that the function is probably the way to go. So for the
case mentioned, it could have:
Ordering.explicit(GRAY_RABBIT, BIG_RABBIT).onResultOf(MAP_EQUALS)
where MAP_EQUALS maps WHITE_RABBIT => GRAY_RABBIT, etc.
It might be worth adding a convenience method
onResultOf(Map<F,? extends T> map)
For the null case, I agree that it would be more handy to have something
built-in, rather than have to repeat the list (and take the extra lookup cost)
in a separate function. Maybe something like:
exceptionsFirst() // any item that would cause a ClassCastException is sorted
first (see nullsFirst)
exceptionsLast() // any item that would cause a ClassCastException is sorted
last (see nullsLast)
or
exceptionsAsNulls() // items causing exceptions are treated as nulls for
ordering.
Original comment by markda...@google.com
on 25 Aug 2010 at 5:29
I want to provide a default ordering for the "nulls".
Example: I have a Map<String, Object> containing a bunch of labeled fields of
userdata. There are some common fields that are expected to be present like
"userId", or "email", but may not be, and there may be many more fields, some
added in the future.
I want an ordering where "userId" comes first, then "email", followed by any
other fields in alphabetical order.
Does that clarify the use case?
What I ended up doing was destructively modifying the map: iterating through a
List of "known fields", and adding them in order and removing them from the
map. Then I sorted the remaining keys and added those.
Devil's advocate: probably the proper way to do this is to have one's "known
fields" in an Enum, with every possible field listed, plus one at the end
called CUSTOM. Then have a FieldName class that has one of two constructors:
one that takes the enum (and validates that null or CUSTOM is not passed-in)
and one that takes a String (for custom fields). This class is Comparable and
sorts first by enum and then by the String...
Original comment by ray.j.gr...@gmail.com
on 14 Oct 2010 at 8:16
At this point I am generally sympathetic to the notion that Ordering.explicit
as currently implemented is insufficient, and we should come up with the thing
that can do all the things that users need. I don't know what that will look
like exactly, yet, but am open to hear specific proposals
Original comment by kevinb@google.com
on 16 Oct 2010 at 5:26
Original comment by fry@google.com
on 26 Jan 2011 at 10:45
Some methods signature ideas to handle equality :
as for this ordering : WHITE_RABBIT = GRAY_RABBIT < SMART_RABBIT < FAST_RABBIT
< SMALL_RABBIT = BIG_RABBIT
Ordering.explicit(newArrayList(WHITE_RABBIT, GRAY_RABBIT),
newArrayList(SMART_RABBIT), newArrayList(FAST_RABBIT),
newArrayList(SMALL_RABBIT, BIG_RABBIT));
Ordering.explicit(Iterable<Iterable<T>> elements)
or using newArrayList alias
Ordering.explicit(eq(WHITE_RABBIT, GRAY_RABBIT), explicit(SMART_RABBIT,
FAST_RABBIT), eq(SMALL_RABBIT, BIG_RABBIT));
or method chaining (looks nice)
Ordering.explicit().eq(WHITE_RABBIT, GRAY_RABBIT).explicit(SMART_RABBIT,
FAST_RABBIT).eq(SMALL_RABBIT, BIG_RABBIT);
or builder
Ordering.explicitBuilder().ascending().eq(WHITE_RABBIT,
GRAY_RABBIT).then(SMART_RABBIT, FAST_RABBIT).eq(SMALL_RABBIT,
BIG_RABBIT).build();
Ordering.explicitBuilder().eq(WHITE_RABBIT,
GRAY_RABBIT).lowerThan(SMART_RABBIT, FAST_RABBIT).eq(SMALL_RABBIT,
BIG_RABBIT).build();
Which one do you prefer ? Other ideas ?
Original comment by amer...@gmail.com
on 1 Feb 2011 at 10:12
Original comment by kevinb@google.com
on 13 Jul 2011 at 6:18
Original comment by kevinb@google.com
on 16 Jul 2011 at 8:37
I'd like to be able to this:
Ordering.explicit(List<T>).unknownsLast().compound(Comparator<T>)
So that I can order by the list, then by the comparator when the item isn't in
the list. Currently I have to add all remaining possible items to the end of
the list pre-sorted by the second Comparator.
Original comment by goo...@sa.me.uk
on 10 Nov 2011 at 10:53
Original comment by fry@google.com
on 10 Dec 2011 at 3:44
Original comment by kevinb@google.com
on 30 May 2012 at 7:43
As I have just run into the problem with handling unknown values I am
interested in helping with a fix.
The proposed solution earlier in this thread requires a lot of unnecessary
code, and needs to use the explicit list twice in the setup chain:
Ordering.explicit(...).nullsFirst().onResultOf(UNKNOWN_TO_NULL_FUNCTION);
I think this proposed syntax is a good solution in keeping with the general
chained approach to building Orderings.
Ordering.explicit(List<T>).unknownsLast().compound(Comparator<T>)
In order to achieve this and to leverage the existing rank map within
ExplicitOrdering we need to have access to this. I think the neatest way to do
this would be to make an inner class of ExplicitOrdering that acts (similarly
to nullsFirstOrdering) as a guard and uses the rank map to check for the
existence of left and right before deferring to ExplicitOrdering.
I would propose the following API changes to allow explicit ordering to take
this form in order to handle unknown objects.
1) Change the visibility of ExplicitOrdering<T> to public
2) Change the factory methods for .explicit(...) in Collection to return
ExplicitOrdering<T> rather than Ordering<T>
3) Add the following methods to ExplicitOrdering<T>
public Ordering<T> unknownsFirst()
public Ordering<T> unknownsLast()
I have a working prototype for this including tests if anyone is interested in
looking at it.
Original comment by drme...@gmail.com
on 1 Oct 2013 at 9:43
This issue has been migrated to GitHub.
It can be found at https://github.com/google/guava/issues/<id>
Original comment by cgdecker@google.com
on 1 Nov 2014 at 4:15
Original comment by cgdecker@google.com
on 1 Nov 2014 at 4:19
Original comment by cgdecker@google.com
on 3 Nov 2014 at 9:10
Original issue reported on code.google.com by
amer...@gmail.com
on 24 Feb 2010 at 1:10Attachments: