For a Java assignment I have to sort by length an ArrayList<String> using the Comparable interface.
What I have done, and it works, is to create a custom object in a class that implements Comparableand set the CompareTo() to use length.
It's ok and it works.
I was just wondering if there is an easier way.
I know that String in Java already implements Comparable interface.
But the natural order is lexicographic or alphabetic, not by length.
I have no idea how I can implement a different CompareTo() for instances of the class String without having to create my object.
Is there a way?
Or am I missing the logic?
(I cannot use Comparator, I have to use the Comparable interface.)
I'm getting frustrated with institutions that shoehorn their curriculum into ridiculous and entirely unrealistic constraints.
In practice, you are going to be using a Comparator<String> which allows you the flexibility to use lambdas to sort the results. It's also incredibly terse, too.
On principle, what you've described is the only other logical approach. The only way you could practically solve this is to create your own class that encapsulates the String instance that you want, and sort that.
It sounds like your wrapper object is the simplest way to meet the silly requirement. Just write a method that compares the lengths of the contained strings.
Related
I study the strategy design pattern and from what I see, there is a very similar way to implement the "behaviors" of an object.
one way is the strategy design pattern. in this way the object 'has-a' strategy that represent the behavior.
the other way is to make this object 'implements' the behavior (interface).
for example, in a game, I have 'Enemy' object and one Enemy is flying and one is driving. so until now, I would think about:
first 'Enemy' object implements Flyable and the second 'Enemy' implements Drivable.
but another solution can be first Enemy 'has-a' FlyingStrategy and the second 'has-a' DrivingStrategy.
I'm trying to find the better solution in terms of good design.
Thanks.
They are not interchangeable . A good example is Comparable vs Comparator in the JDK.
In your case, Comparable represents the implementing-an-interface design. Comparator is an example of the strategy pattern. With the two signatures of Collections.sort, you can do this
Collections.sort(listOfComparables);
or this
Collections.sort(anyList, comparator);
Imagine you have a list of Cars. You might want to sort the list by colour, by number of seats, by horsepower. In this case, it makes no sense to implement Comparable. Cars have no natural ordering; it makes no sense to give preference to one ordering over another by implementing the interface. In this case, all orderings are created equal. If you were to declare a car as Comparable then it would likely not be very intuitive for users of your class. They would probably have to check the implementation or the documentation to work out what order you had intended. You should sort these using Comparators.
Now imagine you have a list of Coins. Coins have a fairly obvious natural ordering: their face value. You could sort your coins by size, or by weight, but their primary reason for existing is to represent different denominations. In this case, not all orderings are created equal. It would make sense here to implement Comparable, and if other orderings are required, you can use Comparators for that.
In a more general sense, the strategy pattern is often best applied when there is no one "preferred" approach. A class can only implement an interface once, but it may be able to make use of many different strategies. It is a kind of inversion of control.
I was going through Java documentation, and I learned that methods in the Arrays class in Java are all static. I don't really understand the reason behind why they made it static.
For example, the following code violates the OO approach, because if I have a type, 'X', then all the methods which acts on it should be inside it:
int[] a = {34, 23, 12};
Arrays.sort(a);
It would be better if they have implemented the following way:
int[] a = {34, 23, 12};
a.sort();
Can anyone explain me a bit on this?
In Java there is no way to extend the functionally of an array. Arrays all inherit from Object but this gives very little. IMHO This is a deficiency of Java.
Instead, to add functionality for arrays, static utility methods are added to classes like Array and Arrays. These methods are static as they are not instance methods.
Good observation. Observe also that not every array can be sorted. Only arrays of primitives and Objects which implement the Comparable interface can be sorted. So a general sort() method that applies to all arrays is not possible. And so we have several overloaded static methods for each of the supported types that are actually sortable.
Update:
#Holger correctly points out in the comments below that one of the overloaded static methods is indeed Arrays.sort(Object[]) but the docs explicitly state:
All elements in the array must implement the Comparable interface.
So it doesn't work for Objects that don't implement Comparable or one of its subinterfaces.
First of all, Arrays is an utility class, which does exactly that: exposes static methods. It is separate from any arr[] instances and has no OO relation to it. There are several classes like that, like Collections or various StringUtils.
Arrays are collections, they are used to store data. Arrays.sort() is an algorithm which sorts the collection. There may be many other algorithms which sort data in different way, all of them would be used in the same way: MyAlgorithm.doSthWithArray(array). Even if there was a sort() method on an array (it would then have to be a SortableArray, because not all Objects can be sorted automatically), all other algorithms would have to be called the old way anyway. Unless there was a visitor pattern introduced... But that makes things too complicated, hence, there is no point.
For a java Collection there's Collections.sort(), even in C++ there is std::sort which works similarly, as does qsort in C . I don't see a problem here, I see consistency.
Static Methods are sometimes used for utility purpose.
So Arrays is utility class for general purpose array operations.
Similarly, Collections is also Util class where utility methods are given.
Arrays are kind of like second-class generics. When you make an array it makes a custom class for the array type, but it's not full featured because they decided how arrays would work before they really fleshed out the language.
That, combined with maintaining backwards compatibility, means that Arrays are stuck with an archaic interface.
It's just an old part of the API.
An array is not an object which stores state, beyond the actual values of int the array. In other words, it's just a "dumb container". It doesn't "know" any behaviour.
A utility class is a class which has just public static methods which are stateless functions. Sorting is stateless because there's nothing remembered between calls to that method. It runs "standalone", applying its formula to whatever object is passed in, as long as that object is "sortable". A second instance of an Arrays class would have behaviour no different, so just have the one static instance.
As Dariusz pointed out, there are different ways of sorting. So you could have MyArrays.betterSort(array) as well as Arrays.sort(array).
If you wanted to have the array "know" how best to sort its own members, you'd have to have your own array class which extends an array.
But what if you had a situation where you wanted different sorting on different times on the the same array? A contrived example, maybe, but there are plenty of similar real-world examples.
And now you're getting complicated. Maybe an array of type T sort differently than type S ....
It's made simple with a static utility and the Comparator<T> interface.
For me this is the perfect solution. I have an array, and I have a class, Arrays, which operates over the data in the array. For example, you may want to hold some random numbers and you will never want to sort or any other utility method you will receive behavior which you don't want. That's why in code design it is good to separate data from the behavior.
You can read about the single responsibility principle.
The Arrays class contains methods that are independent of state, so therefore they should be static. It's essentially a utility class.
While OOP principles don't apply, the current way is clearer, concise, and more readable since you don't have to worry about polymorphism and inheritance. This all reduces scope, which ultimately reduces the chances that you screw something up.
Now, you may ask yourself "Why can't I extend the functionality of an array in Java?". A nice answer is that this introduces potential security holes, which could break system code.
Possible Duplicate of
When should a class be Comparable and/or Comparator?
I understand the difference that is given in this link.
And also in the book that i am referring it is given that we can not use comparable when we need to sort the objects on the basis of more than one fields.
My Question:
I just want an example where we could not possibly use comparable and have to go for comparator in order to compare and please also show that with comparable why can't we compare on two different fields of object.
If you find this question as duplicate please provide link,, i have searched many questions but none has the example that i wanted.
If a class implements Comparable, this defines what is usually considered the natural ordering of it elements. In some cases this is the only ordering that may make sense, in other cases it might be the most widely used ordering. If you look for example at numbers, there is probably only one (total) ordering that makes sense (except maybe for taking the reverse). As others already have pointed out, their are other objects that have other useful orderings. What makes the primary ordering (or if there is even one) depends on your application. If you manage persons with adresses in you application, phonebook sort order could be considered the natural order if this is the most widely used one and sorting by age could be a secondary. Slightly OT: Beware of cases where non equal objects are considered equal wrt to the ordering, this may yield problems with containers like OrderedList etc.
Comparing apples with each other will result in classes of equal apples, like red ones, green ones, old and fresh ones. That's OK as long as you only interested in a rather broad equality. But if you you are going to receive a paycheck you are very happy that you are identifiable within you equality class.
So compareto is good for sorting and clustering and equals/hashcode is got for identification.
Comparable is mostly used when there is a 'known' default sort order and the object or class that we are ordering is editable or owned by the developer making the change.
Comparator is suitable where the class or object being ordered is not owned by the developer making the change like a web service response. It is also preferred when the natural ordering doesn't fit the objective that needs to be accomplished.
In C#, finding an item in an ArrayList that have a certain property, it's quite easy:
mSelectedBoard = mBoardConnections.FirstOrDefault(bcd => bcd.Id == id);
This is the easiest I've found to do the same in Java (wish I could afford MonoTouch for android):
for ( BoardConnectionData bcd : mBoardConnections ) {
if (bcd.getID() == id) {
mSelectedBoard = bcd;
break;
}
}
Am I missing an easier way to do this?
Thanks!
Define a meaningful equals and use Collection.contains.
There are a number of utility libraries that contain implementations using various "am I it?" implementations. (Guava, Commons Collections, etc.)
Another option is to create a typed collection containing utility methods finding elements by arbitrary criteria.
In any case, the code snippet shown shouldn't live in the mainline code, it should be abstracted into its own method, regardless of where it ends up living.
Since there are no closures in Java, there's no really easier way to do it. Of course, you can use Guava, but IMHO it offers only a bit of conciseness for a lot of complexity (for your example, at last, because Guava is quite cool otherwise)
Assuming BoardConnectionData class correctly overrides the equals method based on the ID, the following should tell you if the object is in the list or not:
mBoardConnections.contains(object);
If you inherit from Comparable to test for the id member and use a SortedSet:
BoardConnectionData brd =
sortedSet.tailSet(new BoardConnectionData(searchedId)).first();
It is not more efficient complexity-wise, but it is shorter code. :)
To pile on to Dave Newton's answer. The Collection is an ArrayList, so with an appropriate equals (plus hashCode) implementation on BoardConnectionData, the indexOf method would allow the expression
selectedBoard = boardConnections.getAt(boardConnections.indexOf(new BoardConnectionData(id)))
Of course, it's likely preferable to construct a probe object rather than creating a full-blown instance from only the id.
You really should ask your self if ArrayList is the right data structure. Given similar task, I would choose a Map. Both C# and Java will need O(N) to search in an array. Using a map is O(1). If this is something you need to often then I would suggest the right structure.
Really the only difference between the C# and Java version is that one is shorter and uses closure. As many other people have suggested, you can do the same thing with some existing libraries. No one actually showed any code though. With Guava, you can do:
Iterables.find(new Predicate<Data>(){
public boolean apply(Data d){
return d.id == someId;
)}, list);
Or if you want a default value you can use .find(predicate, list, defaultValue).
If you need to match a single property, and multiple items in the list can have identical values for that property, then you need to loop thru like you are doing. Java has a Collections utility class with a bunch of static methods; it might make sense for you to define your own collections utility methods to handle cases like this.
In general though, if you wan't to find an element, just use indexOf and be sure to implement equals properly.
In Java 8 you can do like this:
mSelectedBoard = mBoardConnections
.stream().filter(bcd -> bcd.Id == id).findFirst().orElse(null);
I'm lost trying to sort an array of AbstractEvents (which can be of type DailyEvent or WeeklyEvent). They can be sorted either using a DescriptionComparator class, a StartTimeComparator class or a EndTimeComparator class. Events are added to a Planner class in an array to make things simpler.
The planner class has a sort method that accepts an instance of one of the Comparator classes (which implement java's Comparator class) mentioned above. So now I need to figure out a way to sort these events but I'm fairly new to Java and don't get much of the lingo I've seen on certain sites. I'm looking for good old pseudocode with some explanation to know what I'm doing and learn from it.
Thanks to anyone who can help!
I am not sure what you want from the sorting .But I can give you a little bit of explanation.The comparator just gives a way to compare objects.For sorting you would be using utility classes like java.util.Arrays which has a sort method. So your Planner class has an array of Events which needs to be sorted. I guess you can use the Arrays.sort(arrayTobeSorted,comparator) inside the Planner class sort method. The comparator object given here would give the actual order of sorting. For example you have a DescriptionComparator which would sort objects based on description or StartTimeComparator which would sort based on start time.
Hope this helps.In Java there are many utility classes .So basic things like sorting are easy to do.