Sorting JDOM elements using Java API - sorting

I need your help with following issue:
In my code I have a list of elements, I need to sort this list according to 2 attributes: season and number.
List example:
<episode_list>
<episode id="280" number="13" season="1">
<title><![CDATA[Bowl Game]]></title>
</episode>
<episode id="314" number="12" season="1">
<title><![CDATA[Piss Test]]></title>
</episode>
<episode id="730" number="11" season="1">
I use Collections.sort(), but getting exception. As I understand I can't use it with JDOM Elements:
List<Element> episodes;
Collections.sort(episodes, new Comparator<Element>() {
#Override
public int compare(Element elem1, Element elem2) {
Integer seasonNumber1 = Integer.valueOf(myService.valueOfAttribute("season", elem1));
Integer seasonNumber2 = Integer.valueOf(myService.valueOfAttribute("season", elem2));
int seasonComp = seasonNumber1.compareTo(seasonNumber2);
if (seasonComp != 0) {
return seasonComp;
} else {
Integer episodeNumber1 = Integer.valueOf(myService.valueOfAttribute("number", elem1));
Integer episodeNumber2 = Integer.valueOf(myService.valueOfAttribute("number", elem2));
return episodeNumber1.compareTo(episodeNumber2);
}
}
});
Exception: java.util.Collections$UnmodifiableList$1.set(Unknown Source)
java.util.Collections.sort(Unknown Source)
Actually I don't need sorted xml, the only thing I need is the episode attribute "id" (for the lowest season and the lowest episode number).
What could you recommend? I have another implementation, where I go through all elements, but I don't think it's a nice solution...I also can create Java class Episode(id, episode, season), transform List to List and sort it, but also don't think it's a good idea. There is also sortContent method for Element, but I'm not sure how to implement it.
I'll appreciate any help.

Content attached to JDOM Elements cannot be sorted using the standard Collections.sort() mechanism because that process does not honour the only-attached-at-one-place-at-a-time rule for XML content.
JDOM has sort() methods built in to the Element class that allows you to sort the chile Elements or other Child content: See The Element.sortChildren() Javadoc for the JDOM way to do it.
Update: Also, for your reference, the error you are getting is because at some point you created an unmodifiable version of the List.... this is not something that happens from JDOM method calls. The error you are getting is because you are trying to modify a List that has been intentionally made read-only.

What's wrong with going through the list and finding the minimum. It is O(n), while sorting is O(n*log(n)). You might use a generic min function, such as the one in guava
Element firstEpisode = Ordering.from(your-comparator).min(episodes.iterator());
If you really want to sort it, why don't you sort new ArrayList<Element>(episodes) (I agree with rolfl that you cannot use Collections.sort for JDOM lists and that the error comes from your use of unmodifiable list).

Related

Kotlin Instantiate Immutable List

I've started using Kotlin as a substitute for java and quite like it. However, I've been unable to find a solution to this without jumping back into java-land:
I have an Iterable<SomeObject> and need to convert it to a list so I can iterate through it more than once. This is an obvious application of an immutable list, as all I need to do is read it several times. How do I actually put that data in the list at the beginning though? (I know it's an interface, but I've been unable to find an implementation of it in documentation)
Possible (if unsatisfactory) solutions:
val valueList = arrayListOf(values)
// iterate through valuelist
or
fun copyIterableToList(values: Iterable<SomeObject>) : List<SomeObject> {
var outList = ArrayList<SomeObject>()
for (value in values) {
outList.add(value)
}
return outList
}
Unless I'm misunderstanding, these end up with MutableLists, which works but feels like a workaround. Is there a similar immutableListOf(Iterable<SomeObject>) method that will instantiate an immutable list object?
In Kotlin, List<T> is a read-only list interface, it has no functions for changing the content, unlike MutableList<T>.
In general, List<T> implementation may be a mutable list (e.g. ArrayList<T>), but if you pass it as a List<T>, no mutating functions will be exposed without casting. Such a list reference is called read-only, stating that the list is not meant to be changed. This is immutability through interfaces which was chosen as the approach to immutability for Kotlin stdlib.
Closer to the question, toList() extension function for Iterable<T> in stdlib will fit: it returns read-only List<T>.
Example:
val iterable: Iterable<Int> = listOf(1, 2, 3)
val list: List<Int> = iterable.toList()

Enumerable.Count() vs property Count [duplicate]

This question already has answers here:
Count property vs Count() method?
(10 answers)
Closed 7 years ago.
Classes that implement System.Collection.ICollection, know how many elements they have in their sequence. They have a property Count which returns the number of sequence. Examples are List, Dictionary and Queue.
Other classes that implement IEnumerable might not implement ICollection. Thy don't have a property count. However you still can know the number of elements in the sequence by enumerating over all elements and counting them.
To me the latter method seems much slower.
The only thing that method Enumerable.Count(this IEnumerable) knows about the sequence is that it implements IEnumerable. It doesn't know that the sequence has a property that gives you the number of elements.
Normally this would mean that if you Count() a List, the function must iterate over all elements.
However, the implementation of Enumerable.Count(IEnumerable) could check if the sequence implements interface ICollection and if so it can return Count instead of enumerating over it.
Question: Is Enumerable.Count(this IEnumerable) smart enough to check if the sequence implements ICollection, or does it always iterate over all elements?
If the latter is the case, would it be smart to extend Enumerable with a Count function that checks if the object implements ICollection and if so return ICollection.Count()?
How about looking in the source code.
On line 1905 you can see the count method with the following lines:
ICollection<TSource> collectionoft = source as ICollection<TSource>;
if (collectionoft != null) return collectionoft.Count;
ICollection collection = source as ICollection;
if (collection != null) return collection.Count;
As you can see, the method uses the ICollection.Count propertie, when the IEnumerable is a ICollection.
Take in account, the following method with the signature Count<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) does not implement this (because of the custom count method you provide ; ) )
EDIT:
It should also be mentioned, that the LongCount methods do not use this property.
Because of all this, there is no need to implement your own Count().

Selenium: finding elements in searchContext

everyone!
I'm stuck with following problem:
There is some
SearchContext searchContext;
By by;
which could be WebDriver or WebElement.
Assume that both of them are already initialized (and we don't know how);
Now we want to find elements with such xpath, seems to do following
List<WebElement> elements = searchContext.findElements(by);
But, if searchContext is WebElement and
by = By.xpath("//div");
it wouldn't work! (no elements would be found), because we need to do
by = By.xpath("./div");
(see Locating child nodes of WebElements in selenium)
But, how i've mentioned, we know nothing about how by was initialized;
So, my question is: is there any way to find elements properly despite the problems above?
I've got two variables: by and searchContext, and I should to find specified element in searchContext.
You can do it in some helper method which will throw Exception if this happens
public List<WebElement> returnSearchContext(By by, SearchContext searchContext){
List<WebElement> elements = searchContext.findElements(by);
if (elements.getSize()>0){
return elements;}
else{
throw new ElementNotFoundException();
}
}
I am writing this without access to any IDE, so I might do some errors in my example code. For instance, I think that the exception will need some parameters. But I hope you get the idea.
As I understand, there is now way to do it.
Only way to do it - is manually specify By.xpath properly:
By child = By.xpath("/div");
By descendant = By.xpath("//div");
in case of WebDriver.isAssignableFrom(searchCOntext.getCLass()),
and
By child = By.xpath("div");
By descendant = By.xpath(".//div");
in case of WebElement.isAssignableFrom(searchCOntext.getCLass()).
IMHO, it's bad.

Grails mapping sort on multiple fields :: Groovy sort on multiple map entries

Stumped on this one. In Grails it seems one cannot define a default sort on multiple columns in domain mapping a la static mapping = { sort 'prop1 desc, prop2 asc' }, or { sort([prop1:'desc', prop2:'asc']) }. Only first column gets sorted, lame.
Similarly, when trying to Groovy sort a Grails findAllBy query on multiple columns, the second sort overrides the first.
def list = [[rowNum:2,position:3],[rowNum:1,position:2],[rowNum:3,position:1]]
list.sort{it.rowNum}.sort{it.position}
Obviously missing the boat on the latter case, the groovy sort. I have seen postings re: implementing comparable, but looking for something more concise if possible.
Here is a Groovy solution. Still essentially implementing a Comparator though.
list.sort { map1, map2 -> map1.rowNum <=> map2.rowNum ?: map1.position <=> map2.position }
Thanks to the link from GreenGiant, we see that the issue is closed as fixed as of version 2.3.
There is also example code:
static mapping =
{ sort([lastname:'asc', name:'asc']) }
It is working for me in 2.4.3
You can use String.format if you know max length. I assumed max 10 lenght:
list.sort { String.format('%010d%010d', it.rowNum, it.position) }

Can we sort an IList partially?

IList<A_Desc,A_premium,B_Desc,B_Premium>
Can I sort two columns A_Desc,A_premium...based on A_Desc ?
And let B_Desc,B_Premium be remain in same order before sorting
First off, a list can only be of one type, and only has one "column" of data, so you actually want two lists and a data type that holds "desc" and "premium". "desc" sounds like a String to me; I don't know what Premium is, but I'll pretend it's a double for lack of better ideas. I don't know what this data is supposed to represent, so to me, it's just some thingie.
public class Thingie{
public String desc;
public double premium;
}
That is, of course, a terrible way to define the class- I should instead have desc and premium be private, and Desc and Premium as public Properties with Get and Set methods. But this is the fastest way for me to get the point across.
It's more canonical to make Thingie implement IComparable, and compare itself to other Thingie objects. But I'm editing an answer I wrote before I knew you needed to write a custom type, and had the freedom to just make it implement IComparable. So here's the IComparer approach, which lets you sort objects that don't sort themselves by telling C# how to sort them.
Implement an IComparer that operates over your custom type.
public class ThingieSorter: IComparer<Thingie>{
public int Compare(Thingie t1, Thingie t2){
int r = t1.desc.CompareTo(t2);
if(r != 0){return r;}
return t1.premium.CompareTo(t2);
}
}
C# doesn't require IList to implement Sort- it might be inefficient if it's a LinkedList. So let's make a new list, based on arrays, which does sort efficiently, and sort it:
public List<Thingie> sortedOf(IList<Thingie> list){
List<Thingie> ret = new List<Thingie>(list);
ret.sort(new ThingieSorter());
return ret;
}
List<Thingie> implements the interface IList<Thingie>, so replacing your original list with this one shouldn't break anything, as long as you have nothing holding onto the original list and magically expecting it to be sorted. If that's happening, refactor your code so it doesn't grab the reference until after your list has been sorted, since it can't be sorted in place.

Resources