I have a LinkedList<Individual> where Individual is a class that has a field processorTime.
It is needed to sort this LinkedList (descending order) basing on a function estimate(processorTime) which returns integers.
Please, tell me how can I do this?
Check this guide here:
http://leepoint.net/notes-java/data/collections/comparators.html
Quotations from the site:
The java.util.Comparator interface can be used to create objects to pass to sort methods or
sorting data structures. A Comparator must define a compare function which takes two
Objects and returns a -1, 0, or 1
Pasted code:
// File: arrays/filelist/Filelistsort.java
// Purpose: List contents of user home directory.
// Demonstrates use of Comparators to sort the
// same array by two different criteria.
// Author: Fred Swartz 2006-Aug-23 Public domain.
import java.util.Arrays;
import java.util.Comparator;
import java.io.*;
public class Filelistsort {
//======================================================= main
public static void main(String[] args) {
//... Create comparators for sorting.
Comparator<File> byDirThenAlpha = new DirAlphaComparator();
Comparator<File> byNameLength = new NameLengthComparator();
//... Create a File object for user directory.
File dir = new File(System.getProperty("user.home"));
File[] children = dir.listFiles();
System.out.println("Files by directory, then alphabetical");
Arrays.sort(children, byDirThenAlpha);
printFileNames(children);
System.out.println("Files by length of name (long first)");
Arrays.sort(children, byNameLength);
printFileNames(children);
}
//============================================= printFileNames
private static void printFileNames(File[] fa){
for (File oneEntry : fa) {
System.out.println(" " + oneEntry.getName());
}
}
}
////////////////////////////////////////////////// DirAlphaComparator
// To sort directories before files, then alphabetically.
class DirAlphaComparator implements Comparator<File> {
// Comparator interface requires defining compare method.
public int compare(File filea, File fileb) {
//... Sort directories before files,
// otherwise alphabetical ignoring case.
if (filea.isDirectory() && !fileb.isDirectory()) {
return -1;
} else if (!filea.isDirectory() && fileb.isDirectory()) {
return 1;
} else {
return filea.getName().compareToIgnoreCase(fileb.getName());
}
}
}
////////////////////////////////////////////////// NameLengthComparator
// To sort by length of file/directory name (longest first).
class NameLengthComparator implements Comparator<File> {
// Comparator interface requires defining compare method.
public int compare(File filea, File fileb) {
int comp = fileb.getName().length() - filea.getName().length();
if (comp != 0) {
//... If different lengths, we're done.
return comp;
} else {
//... If equal lengths, sort alphabetically.
return filea.getName().compareToIgnoreCase(fileb.getName());
}
}
}
Collections.sort(linkedList, new Comparator<Individual>() {
int compare(Individual i1, Individual i2) {
...
}
});
Do you mean the LinkedList is not standard, or the sort order based on processor time is not standard?
If the latter, then all you need to do is use Collections.sort(list,comparator) and provide an appropriate implementation of Comparator<NodeType> for your list. See also "implementing compareTo()" which gives some good related guidance.
Post the code for your node and the desired output, and we can give you more specific direction.
Collections.sort(list,new Comparator<Individual>() {
#Override
public int compare(final Individual i1, final Individual i2) {
return i1.processorTime - i2.processorTime;
}
#Override
public boolean equals(Object foo) {
return false; // doesn't matter, but false is better
}
});
Related
I try to write recursive function which gets an array of flights and returns all the possible paths from source country to dest country.
The function signature in Java:
List<List<String>> printAllPathsUtil(String src, String d,List<Flight> localPathList)
every object of type Flight contain 2 features from and to.
I succeed to write the below code and its run successfuly,but I sent to the function one more parameter : String help -who store the source country.
public List<List<String>> printAllPathsUtil(**String help**,String src, String d,List<Flight> localPathList)
I would appreciate it if someone could please find a way how to use the function without the extra parameter,and show in the code.
Note:I implemented the classes in a minimal way just to have parameters to send to the function, therefore there is no get and set in the classes.
import java.util.ArrayList;
import java.util.List;
public class flligth {
public static void main(String args[]) {
Flight f1 = new Flight("ISRAEL","ROMANIA");
Flight f2 = new Flight("ISRAEL","HOLAND");
Flight f3 = new Flight("ISRAEL","LONDON");
Flight f4 = new Flight("ISRAEL","U.S.A");
Flight f5 = new Flight("HOLAND","LONDON");
Flight f6 = new Flight("LONDON","ROMANIA");
all_flight all_f=new all_flight(6);
all_f.addEdge(f1);f1.print();
all_f.addEdge(f2);f2.print();
all_f.addEdge(f3);f3.print();
all_f.addEdge(f4);f4.print();
all_f.addEdge(f5);f5.print();
all_f.addEdge(f6);f6.print();
List <Flight> localPathList=new ArrayList<>();
all_f.printAllPathsUtil("ISRAEL","ISRAEL","ROMANIA",localPathList);
}
}
class Flight{
String from;
String to;
public Flight(String from ,String to){
this.from=from;
this.to=to;
}
public void print()
{
System.out.print(from+" ");
System.out.println(to);
}
}
class all_flight{
static int current=0;
// adjacency list
public ArrayList<Flight> f;
int index;
// Constructor
public all_flight(int index){
this.index=index;
initFlight();
}
// utility method to initialise
// f list
private void initFlight()
{
f = new ArrayList<Flight>();
}
// add edge from u to v
public void addEdge( Flight path)
{
// Add to list.
f.add(path);
}
public List<List<String>> printAllPathsUtil(String help,String src, String d,List<Flight> localPathList)
{
Flight now = f.stream()
.filter(a -> a.from.equals(src)).findFirst()
.orElse(new Flight("no from","no to"));
if(now.from.equals("no from")){
f.remove(0);
localPathList.clear();
if(!(f.isEmpty())){
return printAllPathsUtil(help,f.get(0).from,d,localPathList);
}
return null;
}
localPathList.add(now);
if(localPathList.get(localPathList.size()-1).to.equals(d)
&& localPathList.get(0).from.equals(help)){
System.out.println("the path is :");
printPath(localPathList);
}
return printAllPathsUtil(help,now.to,d,localPathList);
}
private static void printPath(List<Flight> path)
{
for(Flight v : path)
{
v.print();
}
System.out.println();
}
}
Whenever you invoke the printAllPathsUtil() function, you're passing the same value of help each time. Since the property stays constant for each recursive call, you can simply remove it from the parameters.
Instead, you can create a class attribute origin, and replace the usage of help in the function with self.origin.
If localPathList is empty, then help is src. Otherwise, it's localPathList.get(0).from.
To compare the different objects of the same class with their contents like jobTitleId, classificationId, deptId & classificationId was to be done and do some manipulations later using Set and Map. I was able to do that by simply overriding the equals and hashCode methods of Object class and was able to fetch the information (like in the following Map).
Map<LocationData, List<LocationData>>
The following is the class I used (its been shown to you so that it can be referred for my problem statement):
LocationData class
package com.astreait.bulkloader;
public class LocationData {
String locId, deptId, jobTitleId, classificationId;
#Override
public boolean equals(Object obj) {
LocationData ld = (LocationData)obj;
return this.deptId.equals(ld.deptId) && this.jobTitleId.equals(ld.jobTitleId) && this.classificationId.equals(ld.classificationId) &&
this.locId.equals(ld.locId);
}
#Override
public int hashCode() {
return deptId.hashCode() + jobTitleId.hashCode() + classificationId.hashCode() +locId.hashCode();
}
}
Problem:
I'm already known to which all fields of this object I need to make the comparison.
i.e I'm bound to use the variables named classificationId, deptId, jobTitleId & locId etc.
Need:
I need to customize this logic such that the fields Names (classificationId, deptId, jobTitleId & locId etc) can be pulled dynamically along with their values. So, as far as my understanding I made use of 2 classes (TableClass and ColWithData) such that the List of ColWithData is there in TableClass object.
I'm thinking what if I override the same two methods equals() & hashCode();
such that the same can be achieved.
TableClass class #1
class TableClass{
List<ColWithData> cwdList;
#Override
public boolean equals(Object obj) {
boolean returnVal = false;
// I need to have the logic to be defined such that
// all of the dynamic fields can be compared
return returnVal;
}
#Override
public int hashCode() {
int returnVal = 0;
// I need to have the logic to be defined such that
// all of the dynamic fields can be found for their individual hashCodes
return returnVal;
}
}
ColWithData class #2
class ColWithData{
String col; // here the jobTitleId, classificationId, deptId, locId or any other more fields info can come.
String data; // The corresponding data or value for each jobTitleId, classificationId, deptId, locId or any other more fields.
}
Please let me know if I'm proceeding in the right direction or I should make some any other approach. If it is ok to use the current approach then what should be performed in the equals and hashCode methods?
Finally I need to make the map as: (Its not the concern how I will make, but can be considered as my desired result from this logic)
Map<TableClass, List<TableClass>> finalMap;
EDIT I have been down voted. So, I made some modifications for my requirements again. (Please help me out solving this)
Using this class ColWithData is kind of ugly. You should be using a Map<String,String> :
package mypack;
import java.util.*;
public class TableClass {
/* HashMap containing your values:
map.put("locId", [data]);
...
*/
public Map<String,String> cwdMap;
public Map<String,String> getCwdMap() {
return cwdMap;
}
public void setCwdMap(Map<String,String> cwdMap) {
this.cwdMap = cwdMap;
}
#Override
public boolean equals(Object obj) {
TableClass tClass = (TableClass) obj;
for(String col: this.cwdMap.keyset()){
if (! tClass.cwdMap.get(col).equals(this.cwdMap.get(col)){
return false;
}
}
return true;
}
#Override
public int hashCode() {
int hCode = 0;
for(String col: this.cwdMap.keyset()){
hCode = hCode+cwdMap.get(col).hashCode();
}
return hCode;
}
}
In this code I never check for null values but your probably should.
There is another thing that confuse me in your code:
why use getter/setter if your property (cwdList) is public?
I think I have found the solution and its working for me.
Please let me know if there could be the simple or any other way out finding the solution for this problem.
The code snippet is:
package mypack;
import java.util.*;
public class TableClass {
public List<ColWithData> cwdList;
public List<ColWithData> getCwdList() {
return cwdList;
}
public void setCwdList(List<ColWithData> cwdList) {
this.cwdList = cwdList;
}
#Override
public boolean equals(Object obj) {
TableClass tClass = (TableClass) obj;
boolean returnVal = true;
for(ColWithData cwd: this.getCwdList()){
for(ColWithData innerCwd: tClass.getCwdList()){
if(cwd.getCol().equalsIgnoreCase(innerCwd.getCol())){
if(!cwd.getData().equalsIgnoreCase(innerCwd.getData()))
returnVal = false;
}
}
}
return returnVal;
}
#Override
public int hashCode() {
int hCode = 0;
for(ColWithData cwd: this.getCwdList()){
hCode = hCode+cwd.getData().hashCode();
}
return hCode;
}
}
And finally made a map as said:
Map<TableClass, List<TableClass>> map = new LinkedHashMap<TableClass, List<TableClass>>();
displaying the things as desired.
I have a situation where I will be receiving 2+ ArrayList<Widget> and I need to be able to merge all the lists and remove any duplicate Widget so that I wind up with only 1 ArrayList<Widget> that contains all Widgets from all the merged lists, but without any duplicates.
Assume Widget has an overridden equals method that can be used for determining whether two Widgets are duplicates, although there may be a better way:
public ArrayList<Widget> mergeAndRemoveDupes(ArrayList<Widget> widgets...) {
// ???
}
Looking for the most algorithmically efficient way of accomplishing this. I am happy to use Apache Commons or any other open source libs that would help me out too! Thanks in advance!
For each ArrayList<Widget>, add each element to a Set<Widget> (HashSet or TreeSet, depending on whether they can be ordered in some way, or are hashable) utilizing addAll. Sets contain no duplicates by default.
You can convert this Set back into an (Array)List if you need to at the end.
Note you will need to implement hashCode for your Widget class if you decide to use a HashSet, but if you have an overridden equals, you should do this anyway.
Edit: Here's an example:
//Either the class itself needs to implement Comparable<T>, or a similar
//Comparable instance needs to be passed into a TreeSet
public class Widget implements Comparable<Widget>
{
private final String name;
private final int id;
Widget(String n, int i)
{
name = n;
id = i;
}
public String getName()
{
return name;
}
public int getId()
{
return id;
}
//Something like this already exists in your class
#Override
public boolean equals(Object o)
{
if(o != null && (o instanceof Widget)) {
return ((Widget)o).getName().equals(name) &&
((Widget)o).getId() == id;
}
return false;
}
//This is required for HashSet
//Note that if you override equals, you should override this
//as well. See: http://stackoverflow.com/questions/27581/overriding-equals-and-hashcode-in-java
#Override
public int hashCode()
{
return ((Integer)id).hashCode() + name.hashCode();
}
//This is required for TreeSet
#Override
public int compareTo(Widget w)
{
if(id < w.getId()) return -1;
else if(id > w.getId()) return 1;
return name.compareTo(w.getName());
}
#Override
public String toString()
{
return "Widget: " + name + ", id: " + id;
}
}
If you want to use a TreeSet but don't want to implement Comparable<T> on your Widget class, you can give the set itself a Comparator object:
private Set<Widget> treeSet;
....
treeSet = new TreeSet<Widget>(new Comparator<Widget>() {
public int compare(Widget w1, Widget w2)
{
if(w1.getId() < w2.getId()) return -1;
else if(w1.getId() > w2.getId()) return 1;
return w1.getName().compareTo(w2.getName());
}
});
I would do it this way
Set<Widget> set = new HashSet<>(list1);
set.addAll(list2);
List<Widget> mergeList = new ArrayList<>(set);
Use Set Collection Class,
ArrayList<Widget> mergeList = new ArrayList<widget>();
mergeList.addAll(widgets1);
mergeList.addAll(widgets2);
Set<Widget> set = new HashSet<Widget>(mergeList);
ArrayList<Widget> mergeListWithoutDuplicates = new ArrayList<widget>();
mergeListWithoutDuplicates .addAll(set);
return mergeListWithoutDuplicates;
Now here Set will remove all duplicates values from your ArrayList.
This question already has answers here:
How do I make 2 comparable methods in only one class?
(3 answers)
Closed 8 years ago.
I have some code to sort paths by date modified. I want to also write some code to sort the paths in reverse order, and might later want to add some other sorting methods. Is there any way to do all the sorting from a single class file? Or do I have to create another class PathSortByDateReverse, PathSortByCreated, PathSortByFoo, etc. Also, how would I use the different sorting methods?
import java.nio.file.Path;
import java.util.Comparator;
public class PathSortByDate implements Comparator<Path> {
#Override
public int compare(Path first, Path second) {
long seconddate = second.toFile().lastModified(); // get just the filename
long firstdate = first.toFile().lastModified();
if (firstdate == seconddate) {
return 0;
} else if (firstdate > seconddate) {
return 1;
} else {
return -1;
}
}
}
I then call it from the other class with:
public static ArrayList<Path> sortArrayListByDate(ArrayList<Path> pathlist) {
Collections.sort(pathlist,new PathSortByDate());
return pathlist;
}
Why not go for an anonymous inner classes?
public static final Comparator<Person> ID_DESC
= new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return -1 * p1.getId().comparedTo(p2.getId());
// reversed order
}
};
I would usually do it like this. Notice, the constructor is "private" and there is a "public factory method" to get an instance. There will ever exist two PathComparator instances at any given point. This is a big deal if you are into optimizing your code and using best practices.
import java.nio.file.Path;
import java.util.Comparator;
final public class PathComparator implements Comparator<Path> {
// comparator for in order
final private static PathComparator ascendingOrderComparatorDate = new PathComparator(true);
// comparator for reverse order
final private static PathComparator descendingOrderComparatorDate = new PathComparator(false);
final private int isAscendingOrderInt;
final public PathComparator getPathComparator(boolean isAscendingOrder) {
return isAscendingOrder ? ascendingOrderComparatorDate : descendingOrderComparatorDate;
}
private PathComparator(boolean isAscendingOrder) {
this.isAscendingOrderInt = isAscendingOrder ? 1 : -1;
}
#Override
public int compare(Path first, Path second) {
// for optimization (not required but highly recommended)
if(first == second) return 0;
long seconddate = second.toFile().lastModified(); // get just the filename
long firstdate = first.toFile().lastModified();
if (firstdate == seconddate) {
return 0;
} else if (firstdate > seconddate) {
return isAscendingOrderInt * 1;
} else {
return isAscendingOrderInt * -1;
}
}}
you dont need to make the reverse comparator, just make it and reverse it with
Collections.reverseOrder()
Is it possible to have multiple iterators in a single collection and have each keep track independently? This is assuming no deletes or inserts after the iterators were assigned.
Yes.
Sometimes it's really annoying that answers have to be 30 characters.
Yes, it is possible. That's one reason they are iterators, and not simply methods of the collection.
For example List iterators (defined in AbstractList) hold an int to the current index (for the iterator). If you create multiple iterators and call next() a different number of times, each of them will have its int cursor with a different value.
Yes and no. That depend of the implementation of the interface Iterable<T>.
Usually it should return new instance of a class that implement Iterable interface, the class AbstractList implements this like that:
public Iterator<E> iterator() {
return new Itr(); //Where Itr is an internal private class that implement Itrable<T>
}
If you are using standard Java classes You may expect that this is done this way.
Otherwise You can do a simple test by calling iterator() form the object and then run over first and after that second one, if they are depend the second should not produce any result. But this is very unlikely possible.
You could do something like this:
import java.util.ArrayList;
import java.util.Iterator;
public class Miterate {
abstract class IteratorCaster<E> implements Iterable<E>, Iterator<E> {
int mIteratorIndex = 0;
public boolean hasNext() {
return mStorage.size() > mIteratorIndex;
}
public void remove() {
}
public Iterator<E> iterator() {
return this;
}
}
class FloatCast extends IteratorCaster<Float> {
public Float next() {
Float tFloat = Float.parseFloat((String)mStorage.get(mIteratorIndex));
mIteratorIndex ++;
return tFloat;
}
}
class StringCast extends IteratorCaster<String> {
public String next() {
String tString = (String)mStorage.get(mIteratorIndex);
mIteratorIndex ++;
return tString;
}
}
class IntegerCast extends IteratorCaster<Integer> {
public Integer next() {
Integer tInteger = Integer.parseInt((String)mStorage.get(mIteratorIndex));
mIteratorIndex ++;
return tInteger;
}
}
ArrayList<Object> mStorage;
StringCast mSC;
IntegerCast mIC;
FloatCast mFC;
Miterate() {
mStorage = new ArrayList<Object>();
mSC = new StringCast();
mIC = new IntegerCast();
mFC = new FloatCast();
mStorage.add(new String("1"));
mStorage.add(new String("2"));
mStorage.add(new String("3"));
}
Iterable<String> getStringIterator() {
return mSC;
}
Iterable<Integer> getIntegerIterator() {
return mIC;
}
Iterable<Float> getFloatIterator() {
return mFC;
}
public static void main(String[] args) {
Miterate tMiterate = new Miterate();
for (String tString : tMiterate.getStringIterator()) {
System.out.println(tString);
}
for (Integer tInteger : tMiterate.getIntegerIterator()) {
System.out.println(tInteger);
}
for (Float tFloat : tMiterate.getFloatIterator()) {
System.out.println(tFloat);
}
}
}
With the concurrent collections you can have multiple iterators in different threads even if there inserts and deletes.