collection sorting - sorting

The GDK docs indicate that Collection.sort(Comparator comparator) does not change the collection it is called on, but the code below indicates otherwise. Is this a bug in the implementation, error in the docs, or a misunderstanding on my part?
class ISO3LangComparator implements Comparator<Locale> {
int compare(Locale locale1, Locale locale2) {
locale1.ISO3Language <=> locale2.ISO3Language
}
}
List<Locale> locales = [Locale.FRENCH, Locale.ENGLISH]
def sortedLocales = locales.sort(new ISO3LangComparator())
// This assertion fails
assert locales[0] == frenchLocale

the documentation states:
If the Collection is a List, it is
sorted in place and returned.
Otherwise, the elements are first
placed into a new list which is then
sorted and returned - leaving the
original Collection unchanged.
which is reflected in the implementation of the sort() method
public static <T> List<T> sort(Collection<T> self, Comparator<T> comparator) {
List<T> list = asList(self);
Collections.sort(list, comparator);
return list;
}
the asList method looks whether the given collection is an instanceof java.util.List. If yes, it returns the reference, if not it returns a new java.util.ArrayList instance.
since you are using the [] syntax you are implicitly working with an instance of java.util.List.

Related

Using org.xmlunit.diff.NodeFilters in XMLUnit DiffBuilder

I am using the XMLUnit in JUnit to compare the results of tests. I have a problem wherein there is an Element in my XML which gets the CURRENT TIMESTAMP as the tests run and when compared with the expected output, the results will never match.
To overcome this, I read about using org.xmlunit.diff.NodeFilters, but do not have any examples on how to implement this. The code snippet I have is as below,
final org.xmlunit.diff.Diff documentDiff = DiffBuilder
.compare(sourcExp)
.withTest(sourceActual)
.ignoreComments()
.ignoreWhitespace()
//.withNodeFilter(Node.ELEMENT_NODE)
.build();
return documentDiff.hasDifferences();
My problem is, how do I implement the NodeFilter? What parameter should be passed and should that be passed? There are no samples on this. The NodeFilter method gets Predicate<Node> as the IN parameter. What does Predicate<Node> mean?
Predicate is a functional interface with a single test method that - in the case of NodeFilter receives a DOM Node as argument and returns a boolean. javadoc of Predicate
An implementation of Predicate<Node> can be used to filter nodes for the difference engine and only those Nodes for which the Predicate returns true will be compared. javadoc of setNodeFilter, User-Guide
Assuming your element containing the timestamp was called timestamp you'd use something like
.withNodeFilter(new Predicate<Node>() {
#Override
public boolean test(Node n) {
return !(n instanceof Element &&
"timestamp".equals(Nodes.getQName(n).getLocalPart()));
}
})
or using lambdas
.withNodeFilter(n -> !(n instanceof Element &&
"timestamp".equals(Nodes.getQName(n).getLocalPart())))
This uses XMLUnit's org.xmlunit.util.Nodes to get the element name more easily.
The below code worked for me,
public final class IgnoreNamedElementsDifferenceListener implements
DifferenceListener {
private Set<String> blackList = new HashSet<String>();
public IgnoreNamedElementsDifferenceListener(String... elementNames) {
for (String name : elementNames) {
blackList.add(name);
}
}
public int differenceFound(Difference difference) {
if (difference.getId() == DifferenceConstants.TEXT_VALUE_ID) {
if (blackList.contains(difference.getControlNodeDetail().getNode()
.getParentNode().getNodeName())) {
return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
}
public void skippedComparison(Node node, Node node1) {
}

Supplier <Stream> yields empty stream, but as a list, it's not empty

In my code, I have to iterate through a bunch of objectsof type T more than once. Since some objects may be quite large, I resorted to using a Supplier of Stream<T> instead of collecting them all in a list or set. The method is as follows:
private static Supplier<Stream<T>> streamSupplier(...) {
Iterator<T> iterator = ...;
Iterable<T> iterable = () -> iterator;
return () -> StreamSupport.stream(iterable.spliterator(), false);
}
and elsewhere in the code
Supplier<Stream<T>> supplier = streamSupplier(...);
List<T> ts = supplier.get().collect(Collectors.toList());
return ts.isEmpty(); // <-- true
The problem is that when I call the Supplier#get() method on the supplier returned by the above method, it is always empty. But when I changed my code to return a list, everything is working fine:
private static List<T> listSupplier(...) {
Iterator<T> iterator = ...;
Iterable<T> iterable = () -> iterator;
List<T> ts = Lists.newArrayList(iterable);
return ts; // <-- is populated correctly, NOT empty
}
I thought using a Supplier is the correct way to go if I want to use a stream repeatedly (so that I don't end up with a closed `Stream). What am I doing wrong?
You probably want to do something like this:
private static Supplier<Stream<T>> streamSupplier(...) {
return () -> {
Iterator<T> iterator = ...;
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
};
}
This assumes that the line
Iterator<T> iterator = ...;
creates a fresh iterator each time, independently of any existing iterator.
Also note that you should adjust the way the Spliterator is created, for example, if the size is known, or if there are characteristics such as ordering that are important.
Finally, be very careful with doing
Iterable<T> iterable = () -> iterator;
This is close to being an anti-pattern. While it works in the type system -- calling the resulting Iterable's iterator() method will return an instance of Iterator -- it often won't work. The reason is that most code that uses Iterable instances assumes that it can call iterator() multiple times and get independent iterators. This doesn't do that; it captures the Iterator and returns the same Iterator instance each time. This will cause weird breakage similar to what you're seeing.
It looks like you are trying to create many streams from the same iterator.
Try this:
Iterable<Document> docIterable = () -> ...;
Where the ... is from Iterator<Document> docIterator = ...;
Also, why are you returning a Supplier<Stream<Document>> instead of just Stream<Document>?

Spring SpEL chooses wrong method to invoke

I'm trying to evaluate the following SpEL expression (Spring-expression version 3.1.1):
T(com.google.common.collect.Lists).newArrayList(#iterable)
where #iterable is of type java.lang.Iterable.
Google Guava com.google.common.collect.Lists (version 14.0) does have a method newArrayList(Iterable) but for some reason SpEL chooses to invoke a different method: newArrayList(Object[])
I dived into the code and found the issue to be with org.springframework.expression.spel.support.ReflectiveMethodResolver implementation: it seems to be sensitive to the manner in which methods are sorted by the java.lang.Class::getMethods.
If 2 methods match the invocation (in the case one of the methods is varargs), the later method (in the order) will be invoked, instead of choosing the method that isn't varargs (which is more specific).
It seems like JDK doesn't guarantee the order the methods are sorted: different runs show different order.
Is there a way to overcome this issue?
You can use the collection projections of Spring EL to select all from iterable and convert it to list:
"#iterable.?[true]"
A simple example to test:
Iterable<Integer> it = () -> new Iterator<Integer>() {
private int[] a = new int[]{1, 2, 3};
private int index = 0;
#Override
public boolean hasNext() {
return index < a.length;
}
#Override
public Integer next() {
return a[index++];
}
};
Tmp tmp = new Tmp();
tmp.setO(it);
StandardEvaluationContext context = new StandardEvaluationContext(tmp);
ArrayList<Integer> list = parser.parseExpression("o.?[true]").getValue(context,
ArrayList.class);

LINQ - Sorting a custom list

I want to do the same as explained here:
Sorting a list using Lambda/Linq to objects
that is:
public enum SortDirection { Ascending, Descending }
public void Sort<TKey>(ref List<Employee> list,
Func<Employee, TKey> sorter, SortDirection direction)
{
if (direction == SortDirection.Ascending)
list = list.OrderBy(sorter);
else
list = list.OrderByDescending(sorter);
}
to call it he said to do:
Sort(ref employees, e => e.DOB, SortDirection.Descending);
but I do not understand what TKey is refering to and as I can see in the call it is missed the generic TKey.
Could you explain me what is TKey and how to use it?
I suppose I can use another name for the method, it is not necessary to be Sort, right?
thanks!
You sort by the key which is of type TKey and must implement IComparable<TKey>. For instance:
// key: Firstname
// TKey: string (which is IComparable<String>
list.OrderBy(person => person.Firstname);
The above code sorts by firstname, which is what you define using the sorter. And yes, you can give your method any name you like. It does not have to be named Sort.
Improvement Suggestion (indirectly related to the question)
instead of changing list and passing it as a reference I'd suggest you to consider the following implementation:
public IOrderedEnumerable<Employee> Sort<TKey>(IEnumerable<Employee> list, Func<Employee, TKey> sorter, SortDirection direction);
{
IOrderedEnumerable<Employee> result;
if (direction == SortDirection.Ascending)
result = list.OrderBy(sorter);
else
result = list.OrderByDescending(sorter);
return result;
}
You could then return a new ordered enumerable of Employee objects instead of changing the old one and use any enumerable instead of List object only. This gives you more flexibility and is closer to the LINQ implementation which people tend to be used to.

Combo Box Item comparison and compiler warnings

In VisualStudio (Pro 2008), I have just noticed some inconsistent behaviour and wondered if there was any logical reasoning behind it
In a WinForms project, if I use the line
if(myComboBox.Items[i] == myObject)
I get a compiler warning that I might get 'Possible unintended references' as I am comparing type object to type MyObject. Fair enough.
However, if I instead use an interface to compare against:
if(myComboBox.Items[i] == iMyInterface)
the compile warning goes away.
Can anyone think if there is any logical reason why this should happen, or just an artifact of the compiler not to check interfaces for comparison warnings. Any thoughts?
EDIT In my example, the combobox was bound to a List, but that list was generated using list<IMyInterface>.Cast<MyObject>().ToList<MyObject>()
Its as if the compiler is only taking still assuming I am binding to the List of IMyInterface.
(Object and Interface methods have been changed to protect the innocent)
The compile warning for the first sample is because any custom == operator for your class would be ignored and the references compared (maybe not what you intended, hence the warning).
It's not possible to specify that an operator should be overridden on an interface, so this will always be a reference comparison. The warning is not needed because you should always expect this.
Here's an example of overriding the == operator:
class Program
{
static void Main(string[] args)
{
object t1 = new MyTest() { Key = 1 };
MyTest t2 = new MyTest() { Key = 1 };
Console.WriteLine((MyTest)t1 == t2); // Uses overriden == operator, returns true
Console.WriteLine(t1 == t2); // Reference comparison, returns false
}
}
public class MyTest
{
public int Key { get; set; }
public override bool Equals(object obj)
{
return this.Key == (obj as MyTest).Key;
}
public override int GetHashCode()
{
return this.Key.GetHashCode();
}
public static bool operator ==(MyTest t1, MyTest t2)
{
return t1.Equals(t2);
}
public static bool operator !=(MyTest t1, MyTest t2)
{
return !t1.Equals(t2);
}
}
The MyTest class is considered equal if the Key property is equal. If you were to create an interface, you cannot specify that it should include a custom == operator and therefore the comparison would always be a reference comparison (and therefore false in the case of our sample code).
Lagerdalek,
The warning is generated because you need to cast the item from the Items collection back into the orginal type that was bound to the combo box, before comparing; otherwise you may get unexpected results as the compiler warns.
Here is an example:
myComboBox.DataSource = Collection<Car>;
So if the combo box is bound to a collection of car objects you would cast them back before comparison:
if((car)myComboBox.Items[i] == thisCar)
Then you shouldn't get any warnings.
Another method you could do is:
using(myComboBox.Items[i] as car){
if(myComboBox.Items[i] == thisCar)
}
Let me know. Good Luck! I'm going from memory, I hope I didn't mistype anything. :o)

Resources