implant a comparator to string array in java - java

Suppose I have a method - private static void sort(String[] arr)
Now I want to sort this array using the comparator - String.CASE_INSENSITIVE_ORDER
Is it possible to set this as the default comparator to the String arr before passing
the argument to this function sort. It's like I wont have to change anything inside the sort function to modify its behavior. It's like the comparator gets implanted into
the arr

Arrays are meant to be basic, simple containers.
If you want more features, use a class from the Java Collections Framework.
If your elements are distinct (no duplicates need be tracked), use a NavigableSet implementation. Java bundles two. One is TreeSet.
NavigableSet< String > navSet = new TreeSet<>() ;
By default, the navigable set uses the “natural order” of your objects, by calling their compareTo method. Alternatively, you can pass a Comparator to the constructor, to be used for sorting.
In your case the String class carries a Comparator implementation as a constant: String.CASE_INSENSITIVE_ORDER .
NavigableSet< String > navSet = new TreeSet<>( String.CASE_INSENSITIVE_ORDER ) ;
Caveat: That comparator does not account for locale in sorting your strings. For locale-savvy sorting, use a Collator instead.
You said:
It's like I wont have to change anything inside the sort function to modify its behavior. It's like the comparator gets implanted into the arr
That is exactly what you get by specifying a Comparator for a collection class.

Related

Compare 2 object arrays in java, perform condition and modify list data?

I have 2 lists in java, and I need to validate when there is a match, I set a field of the first list, I tried to do it with streams, but I don't know how to compare the two lists, list don't have same kind of elements I want to do something like this:
public static List<TransactionalityIdDBDTO> getVariationDateRange(List<TransactionalityIdDBDTO> list1,
List<TransactionalityIdDBDTO> list2){
List<TransactionalityIdDBDTO> idDBDTOS= new ArrayList<>();
Iterator prueba=list1.iterator();
while(prueba.hasNext()){
TransactionalityIdDBDTO transactionalityIdDBDTO=(TransactionalityIdDBDTO) prueba.next();
if(transactionalityIdDBDTO.get_id().equals(list2.get_id())){
transactionalityIdDBDTO.setVariation("1232");
idDBDTOS.add(transactionalityIdDBDTO);
}
}
return idDBDTOS;
}
Clase TransactionalityIdDBDTO
public class TransactionalityIdDBDTO extends AbstractDTO {
private TransactionalityDBDTO _id;
private String totalTransaction;
private List<String> idResult;
private String variation;
You can compare lists using equals. e.g
list1.equals(list2);
However,
order is important. If lists contain the same content but in different order they will be considered unequal.
the objects the lists hold must override equals. The criteria for what constitutes two objects of TransactionalityIdDBDTO to be equal are up to you. Based on your code, it seems that id is a good start.
if you plan on using those objects as keys in a map, you must override hashCode too (it's a good idea to do this anyway).
if the lists are not in order but you want to consider them equal, then you should probably sort them first based on the id. You can do that like this.
list1.sort(Comparator.comparing(TransTransactionalityIdDBDTO::get_id));
list2.sort(Comparator.comparing(TransTransactionalityIdDBDTO::get_id));
Objects like String, Integer, and other wrapper classes implement Comparable which means they can be compared to each other of the same type using the above. But instead of get_id which returns a String, say you had get get_Foo. Then the Foo class would need to implement comparable or you would have to provide a more detailed comparator on which to sort.
There are many examples of Comparing objects on the site. I recommend you search them using the [hashCode], [equals], [comparable] and [comparator] tags. Imo, understanding these and how they work are essential for a reasonable working knowledge of Java.

Mutli raw type in java

I have an ArrayList of something. I don't now correctly, but I'm pretty sure, that the Object has the compareTo(Object), which returns int in any cases. So, if I want to implement a sort(ArrayList), Objects may by strings, or integers.
private static void sort(ArrayList<String/Integers, or SomethingElse, not sure now> list)
I tried to search something like multi raw type, but I didn't find anything.
How should I do it?
If the List consists of String elements, it will be sorted into alphabetical order. If it consists of Date elements, it will be sorted into chronological order. It will sort any any object/type that contain compareTo() (implements Comparable)
Reference: Collections.sort(list)
If you try to sort a list, the elements of which do not implement Comparable, Collections.sort(list) will throw a ClassCastException

Store String+Integer pair in dynamic array?

I need to store few data pairs in array. Maybe few dozens. I only need to append, no need to delete, no need to search. Then I will access by index. Each pair is String value and Integer value. Java provides so many way to do this, which is the common practice for something like that? Two arrays? A class in an array?
I know how to do this in JavaScript:
var data = []
data.push(['Some name', 100])
//somewhere else
data.push(['Other name', 200])
but I need a solution for Java
Thank you.
For example you can create Pair class (or use implementations from apache commons) to store two elements in List.
List<Pair<String, Integer>> l = new ArrayList<>();
l.add(new Pair<String, Integer>("Some name", 100));
See Generic pair class and Java Pair<T,N> class implementation to see how you can implement Pair class.
It really depends, but in general I think it is better to create an object and use a list of it:
public class MyObject {
private String myString;
private Integer myInt;
// getters setters
}
And use:
List<MyObject> = new ArrayList<>();
(you can also use Pair instead)
If the strings (or ints) are unique, you can use Map, but it is harder to get the insert index.
Another option is just two lists, one for Strings, one for Integers, and use same index in both lists.
I go by using POJO as suggested above for this as this helps to define getter and setter for all the attributes of POJO, compare the objects by overriding equals and hashCode methods. By using getter and setter you know what is stored in what field and comparison can provide you sorting of objects as per your requirements. So this approach is cleaner and extensible for accommodating new requirements too. Also as you are putting data with sequential key so each instance of Pojo can be put in List (if required in sorted order.

Java String Array

i have two array
String a[]={"11","02","43","24","05","86","37","28","29","10"};
String b[]={"a","c","f","q","w","x","z","x","s","r"};
i want to sort array a[] in ascending order
and the result may like
String a[]={"02","05","10","11","24","28","29","37","43","86"};
String b[]={"c","w","r","a","q","x","s","z","f","x"};
how can i get result like above using java?
any sorting method available in java?
The easiest way would be to link the 2 pieces of data together in some way instead of having them in separate arrays. Many people have suggested a Map which would work great. Depending on exactly what you are trying to do, I would also consider a new class with 2 variables that implement Comparable. Comparable defines the natural ordering of a class when it is in a Collection (in this instance an array) if Collections.sort is not given a different Comparator to use. It would look something like this:
public class Data implements Comparable{
private String stringOne;
private String stringTwo;
#Override
public int compareTo(Object obj) {
stringOne.compareTo((String)obj);
}
Somewhere else call:
Collections.sort(locationOfDataCollection);
You could then create one Collection of Data and access the other String with a getter method. This implementation also would make it simple in future (see Strategy Design) if in some instances the natural order needed to be overridden with a new Comparator (e.g. sort by stringTwo).
Since you have 2 related sets of data, I would either link these via a Pair<String,String> type object and then into a List<Pair>, or put them into a Map<String,String>.
Perhaps the first solution is more intuitive e.g.
public class Pair implements Comparable<Pair> {
public String first;
public String second;
// equals/hashcode etc.
}
Once they're in a standard Java collection, numerous solutions exist for sorting these. e.g. in the above Pair I've implemented the Comparable<T> interface which the Collections sorting mechanisms will make use of.
There is no methods for directly doing this in Java. You have two options.
1) Define a Map<String, String>, put all the pairs in it (like ("11", "a")). Sort first array (or the keys of the map) and retrieve the elements of the map in that order.
2) Create an object that holds each par, create a List with it, and sort comparing only by the number (implement Comparable or create a Comparator).
One issue you'll need to be aware of is that Strings don't sort according to the same rules as integers. You are likely to be surprised by what you get if you leave the array by which you sort as String.

Java - Distinct List of Objects

I have a list/collection of objects that may or may not have the same property values. What's the easiest way to get a distinct list of the objects with equal properties? Is one collection type best suited for this purpose? For example, in C# I could do something like the following with LINQ.
var recipients = (from recipient in recipientList
select recipient).Distinct();
My initial thought was to use lambdaj (link text), but it doesn't appear to support this.
return new ArrayList(new HashSet(recipients));
Use an implementation of the interface Set<T> (class T may need a custom .equals() method, and you may have to implement that .equals() yourself). Typically a HashSet does it out of the box : it uses Object.hashCode() and Object.equals() method to compare objects. That should be unique enough for simple objects. If not, you'll have to implement T.equals() and T.hashCode() accordingly.
See Gaurav Saini's comment below for libraries helping to implement equals and hashcode.
Place them in a TreeSet which holds a custom Comparator, which checks the properties you need:
SortedSet<MyObject> set = new TreeSet<MyObject>(new Comparator<MyObject>(){
public int compare(MyObject o1, MyObject o2) {
// return 0 if objects are equal in terms of your properties
}
});
set.addAll(myList); // eliminate duplicates
Java 8:
recipients = recipients.stream()
.distinct()
.collect(Collectors.toList());
See java.util.stream.Stream#distinct.
order preserving version of the above response
return new ArrayList(new LinkedHashSet(recipients));
If you're using Eclipse Collections, you can use the method distinct().
ListIterable<Integer> integers = Lists.mutable.with(1, 3, 1, 2, 2, 1);
Assert.assertEquals(
Lists.mutable.with(1, 3, 2),
integers.distinct());
The advantage of using distinct() instead of converting to a Set and then back to a List is that distinct() preserves the order of the original List, retaining the first occurrence of each element. It's implemented by using both a Set and a List.
MutableSet<T> seenSoFar = Sets.mutable.with();
int size = list.size();
for (int i = 0; i < size; i++)
{
T item = list.get(i);
if (seenSoFar.add(item))
{
targetCollection.add(item);
}
}
return targetCollection;
If you cannot convert your original List into an Eclipse Collections type, you can use ListAdapter to get the same API.
MutableList<Integer> distinct = ListAdapter.adapt(integers).distinct();
Note: I am a committer for Eclipse Collections.
You can use a Set. There's couple of implementations:
HashSet uses an object's hashCode and equals.
TreeSet uses compareTo (defined by Comparable) or compare (defined by Comparator). Keep in mind that the comparison must be consistent with equals. See TreeSet JavaDocs for more info.
Also keep in mind that if you override equals you must override hashCode such that two equals objects has the same hash code.
The ordinary way of doing this would be to convert to a Set, then back to a List. But you can get fancy with Functional Java. If you liked Lamdaj, you'll love FJ.
recipients = recipients
.sort(recipientOrd)
.group(recipientOrd.equal())
.map(List.<Recipient>head_());
You'll need to have defined an ordering for recipients, recipientOrd. Something like:
Ord<Recipient> recipientOrd = ord(new F2<Recipient, Recipient, Ordering>() {
public Ordering f(Recipient r1, Recipient r2) {
return stringOrd.compare(r1.getEmailAddress(), r2.getEmailAddress());
}
});
Works even if you don't have control of equals() and hashCode() on the Recipient class.
Actually lambdaj implements this feature through the selectDistinctArgument method
http://lambdaj.googlecode.com/svn/trunk/html/apidocs/ch/lambdaj/Lambda.html#selectDistinctArgument(java.lang.Object,%20A)

Categories