I am sorting collection wrt date as follows but in collection some date field are empty and it is not sorting correctly.
public class DateComparator implements Comparator<MyList>{
private static boolean isAscending;
private static final String TAG = "DateComparator";
public static boolean isAscending() {
return isAscending;
}
public static void setAscending(boolean isAscending) {
DateComparator.isAscending = isAscending;
}
#Override
public int compare(MyList lhs, MyList rhs) {
String pattern = "MM/dd/yyyy";
try {
String dueDateLHS = lhs.getDueDate();//some field are null
String dueDateRHS = rhs.getDueDate();//some field are null
if(dueDateLHS!=null && dueDateRHS!=null){
SimpleDateFormat dateFormatLHS = new SimpleDateFormat(pattern);
SimpleDateFormat dateFormatRHS = new SimpleDateFormat(pattern);
Date dateLHS = dateFormatLHS.parse(dueDateLHS);
Date dateRHS = dateFormatRHS.parse(dueDateRHS);
if(isAscending)
return dateLHS.compareTo(dateRHS);
else
return dateRHS.compareTo(dateLHS);
}
} catch (ParseException e) {
Log.e(TAG, ""+e.getMessage());
e.printStackTrace();
}
return -1;
}
}
How should I resolve this issue?
You're not handling the case where one side is null and the other is not. You need to add something like:
else if(dueDateLHS == null && dueDateRHS!=null){
if(isAscending) {
return -1;
} else
return 1;
}
} else if (dueDateLHS != null && dueDateRHS==null){
//etc
} else if (dueDateLHS == null && dueDateRHS==null){
return 0;
}
Related
I'm reading the source code of spring boot. I found a problem when reading the SpringFactoriesLoader.loadFactoryNames. The URLClassPath.getResources return the implementation of Enumeration<Resource>, but the value has extra two fields name and check. So, when do the two fields be added into the return value?
public Enumeration<Resource> getResources(final String var1, final boolean var2) {
return new Enumeration<Resource>() {
private int index = 0;
private int[] cache = URLClassPath.this.getLookupCache(var1);
private Resource res = null;
private boolean next() {
if (this.res != null) {
return true;
} else {
do {
URLClassPath.Loader var1x;
if ((var1x = URLClassPath.this.getNextLoader(this.cache, this.index++)) == null) {
return false;
}
this.res = var1x.getResource(var1, var2);
} while(this.res == null);
return true;
}
}
public boolean hasMoreElements() {
return this.next();
}
public Resource nextElement() {
if (!this.next()) {
throw new NoSuchElementException();
} else {
Resource var1x = this.res;
this.res = null;
return var1x;
}
}
};
}
I'm using the Intellij to debug the program, the result is
Result instance is an anonymous class in this case and it captures the values of the getResources parameters (final String var1, final boolean var2).
This question already has answers here:
Calculating days between two dates with Java
(16 answers)
Closed 6 years ago.
I want to get the current date and time the variables
int d,m,y,h,s;
So far I have made a class for Date that could let the user enter the date and it checks for the validity of the date but I am not sure how to get the number of days passed since and also the current date.
My class Date ->
import ShortHand.*;
public class Date {
public static char[] digits={'0','1','2','3','4','5','6','7','8','9'};
int d=0,m=0,y=0;
public int getD() {
return d;
}
public int getM() {
return m;
}
public int getY() {
return y;
}
public Date(int dd,int mm,int yy)
{
if (checkDate(dd,mm,yy)==false)
throw new IllegalArgumentException("Invalid Date");
this.d=dd;
this.m=mm;
this.y=yy;
}
public static boolean checkDate(int d,int m,int y)
{
if (m<1||d<1||y<1)
return false;
if (m>12)
return false;
if (m==2&&checkLeap(y)&&d>29)
return false;
if (m==2&&!(checkLeap(y))&&m>28)
return false;
if ((m==1||m==3||m==5||m==7||m==8||m==10||m==12)&&d>31)
return false;
if ((m==4||m==6||m==8||m==11)&&d>30)
return false;
return true;
}
public static boolean checkLeap(int y)
{
if (y%100!=0)
{
if (y%4==0)
return true;
}
else if (y%400==0)
return true;
return false;
}
public static Date takeIn(String msg)throws java.io.IOException
{
int d,m,y;
while(true)
{
boolean f=true;
u.pln(msg+"[dd-mm-yyyy]");
String in=u.iBs();
if (in.length()!=10)
{
u.pln("Please Enter a Valid Date");
continue;
}
for (int i=0;i<10;i++)
{
if (i!=2&&i!=5)
{
if (Arr.check(in.charAt(i), digits)==false)
{
u.pln("Invalid Input");
f=false;
break;
}
}
}
if (f==false)
continue;
String t=in.substring(0,2);
d=Integer.parseInt(t);
t=in.substring(3,5);
m=Integer.parseInt(t);
t=in.substring(6);
y=Integer.parseInt(t);
if (checkDate(d,m,y))
break;
}
return new Date(d,m,y);
}
#Override
public String toString() {
return this.d+"/"+this.m+"/"+this.y;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Date other = (Date) obj;
if (d != other.d) {
return false;
}
if (m != other.m) {
return false;
}
if (y != other.y) {
return false;
}
return true;
}
}
There is LocalDate class in Java 8 which will do the difference (and much more):
LocalDate start = LocalDate.of(startYear, startMonth, startDay);
LocalDate end = LocalDate.of(endYear, endMonth, endDay);
long diff = start.until(end, ChronoUnit.DAYS);
To assign the current date into end use now() method:
LocalDate end = LocalDate.now();
To get current date you can use Java 8 Date Time API
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate localDate = LocalDate.now();
System.out.println(dtf.format(localDate));
Output of below class is :
size is 3
size is 1
But if I change the TreeSet to a HashSet so line :
Set<SuggestionDetailBean> set = new TreeSet<SuggestionDetailBean>();
becomes
Set<SuggestionDetailBean> set = new HashSet<SuggestionDetailBean>();
the output is :
size is 3
size is 2
Shout using HashSet or TreeSet not change the size of Set ?
Using HashSet seems to behave as expected because it is removing duplicates but when I use TreeSet the duplicates remain ?
I think the hashcode and equals methods in SuggestionDetailBean are overriden correctly ?
Here is the code :
public class TestSet {
public static void main(String args[]){
SuggestionDetailBean s = new SuggestionDetailBean();
s.setTagList("teddst");
s.setUrl("testurl");
SuggestionDetailBean s2 = new SuggestionDetailBean();
s2.setTagList("teddst");
s2.setUrl("testurl");
SuggestionDetailBean s3 = new SuggestionDetailBean();
s3.setTagList("tessdafat");
s3.setUrl("fdfaasdfredtestur ldd");
List<SuggestionDetailBean> list = new ArrayList<SuggestionDetailBean>();
list.add(s);
list.add(s2);
list.add(s3);
Set<SuggestionDetailBean> set = new TreeSet<SuggestionDetailBean>();
set.addAll(list);
System.out.println("size is "+list.size());
System.out.println("size is "+set.size());
}
}
public class SuggestionDetailBean implements Comparable<Object> {
private String url;
private String tagList;
private String numberOfRecommendations;
private String date;
private String time;
private String summary;
private String truncatedUrl;
public void setTruncatedUrl(String truncatedUrl) {
if(truncatedUrl.length() > 20){
truncatedUrl = truncatedUrl.substring(0, 20)+"...";
}
this.truncatedUrl = truncatedUrl;
}
public String getSummary() {
if(summary == null){
return "";
}
else {
return summary;
}
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public String getTruncatedUrl() {
return this.truncatedUrl;
}
public void setTime(String time) {
this.time = time;
}
public String getTagList() {
if(tagList == null){
return "";
}
else {
return tagList;
}
}
public void setTagList(String tagList) {
this.tagList = tagList;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getNumberOfRecommendations() {
return numberOfRecommendations;
}
public void setNumberOfRecommendations(String numberOfRecommendations) {
this.numberOfRecommendations = numberOfRecommendations;
}
#Override
public int compareTo(Object o) {
DateFormat formatter;
Date date1 = null;
Date date2 = null;
SuggestionDetailBean other = (SuggestionDetailBean) o;
if(this.date == null || other.date == null){
return 0;
}
formatter = new SimpleDateFormat(SimpleDateFormatEnum.DATE.getSdfType()+" "+SimpleDateFormatEnum.TIME.getSdfType());
try {
date1 = (Date) formatter.parse(this.date + " " + this.time);
date2 = (Date) formatter.parse(other.date + " " + other.time);
} catch (ParseException e) {
System.out.println("Exception thrown in"+this.getClass().getName()+", compareTo method");
e.printStackTrace();
}
catch(NullPointerException npe){
System.out.println("Exception thrown "+npe.getMessage()+" date1 is "+date1+" date2 is "+date2);
}
return date2.compareTo(date1);
}
#Override
public int hashCode() {
return this.url.hashCode();
}
#Override
public boolean equals(Object obj) {
SuggestionDetailBean suggestionDetailBean = (SuggestionDetailBean) obj;
if(StringUtils.isEmpty(this.getTagList())){
return this.getUrl().equals(suggestionDetailBean.getUrl());
}
else {
return (this.getTagList().equals(suggestionDetailBean.getTagList())) &&
(this.getUrl().equals(suggestionDetailBean.getUrl()));
}
}
}
Edit :
Note : if I convert the hashset to a treeset using :
Set<SuggestionDetailBean> sortedSet = new TreeSet<SuggestionDetailBean>(hashset);
Then correct sorting is maintained, as the removal of duplicates is based on the object hashcode and equals methods not the compareto method.
According to the Javadoc for TreeSet:
Note that the ordering maintained by a set (whether or not an explicit
comparator is provided) must be consistent with equals if it is to
correctly implement the Set interface. (See Comparable
or Comparator for a precise definition of consistent with
equals.) This is so because the Set interface is defined in
terms of the equals operation, but a TreeSet instance
performs all element comparisons using its compareTo (or
compare) method, so two elements that are deemed equal by this method
are, from the standpoint of the set, equal. The behavior of a set
is well-defined even if its ordering is inconsistent with equals; it
just fails to obey the general contract of the Set interface.
So, the problem is with your compareTo method: either it's giving inconsistent results, or else it's giving consistent results that don't obey the rule that a.compareTo(b) == 0 if and only if a.equals(b).
For example, this bit:
if(this.date == null || other.date == null){
return 0;
}
means "if either this or other has date == null, then report that this and other are equal", which is certainly not what you want.
I'm trying to create a Manga app for Android where the each Chapter has its own Title,Publication Date, Description, etc. And each of said chapters belongs to a Manga object. Which would be a collection of Chapters and would include a list of the titles plus the Title of the Manga itself and the author('s) name(s). The data itself would be parsed from different webpages (but that's another mater).
My confusion is about the class declarations. (i.e. implements, extends)
Ive tried many things but as of right now my code consists of having chapters as an inner class like so:
public abstract class Manga implements MangaList {
public String name;
public String author;
public int chapters;
// names of the XML tags
static final String CHANNEL = "channel";
static final String PUB_DATE = "pubDate";
static final String DESCRIPTION = "description";
static final String LINK = "link";
static final String TITLE = "title";
static final String ITEM = "item";
private final URL feedUrl;
protected Manga(String feedUrl){
try {
this.feedUrl = new URL(feedUrl);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
protected InputStream getInputStream() {
try {
return feedUrl.openConnection().getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
List<Chapter> Chapter;
public class Chapter implements Comparable<Chapter> {
final SimpleDateFormat FORMATTER =
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
private String title;
private URL link;
private String description;
private Date date;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title.trim();
}
// getters and setters omitted for brevity
public URL getLink() {
return link;
}
public void setLink(String link) {
try {
this.link = new URL(link);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description.trim();
}
public String getDate() {
return FORMATTER.format(this.date);
}
public void setDate(String date) {
// pad the date if necessary
while (!date.endsWith("00")){
date += "0";
}
date = "";
try {
this.date = FORMATTER.parse(date.trim());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
public Chapter copy(){
Chapter copy = new Chapter();
copy.title = title;
copy.link = link;
copy.description = description;
copy.date = date;
return copy;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Title: ");
sb.append(title);
sb.append('\n');
sb.append("Date: ");
sb.append(this.getDate());
sb.append('\n');
sb.append("Link: ");
sb.append(link);
sb.append('\n');
sb.append("Description: ");
sb.append(description);
return sb.toString();
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((date == null) ? 0 : date.hashCode());
result = prime * result
+ ((description == null) ? 0 : description.hashCode());
result = prime * result + ((link == null) ? 0 : link.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Chapter other = (Chapter) obj;
if (date == null) {
if (other.date != null)
return false;
} else if (!date.equals(other.date))
return false;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (link == null) {
if (other.link != null)
return false;
} else if (!link.equals(other.link))
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
return true;
}
public int compareTo(Chapter another) {
if (another == null) return 1;
// sort descending, most recent first
return another.date.compareTo(date);
}
}
My question is if this is an appropriate format or if there is a simpler way to create a List of Mangas, each with its own set of Chapters?
EDIT: I've looked it up and decided that using an SQLite Database would be a much simpler way to keep track of the large amount of data I will be parsing.
This way I can maintain two databases. One for Manga titles and authors, and another for the chapters and relevant information. The Related chapters will be linked to the Manga in each table through a reference ID.
I definitely think that there is an easier way to do this; however, it really depends on what you overall goal is. If you are trying to display this in a list you might consider using ListView, but if you are just using the data for content, then you can probably do something similar to what you have. Ultimately, you need to figure out what you are going to do with the app, then you can figure out the easiest way to implement it. Remember though: easier isn't always better. Try and think long term about your project as in who is going to be maintaining this, is it going to grow or shrink, and whether you will add features.
As for extends and implements they are subclasses and interfaces, respectively and has different rules regarding it and more information can be found here: http://docs.oracle.com/javase/tutorial/java/concepts/interface.html
Best of luck!
I have an array list that contains Quote objects. I want to be able to sort alphabetically by name, by change, and by percent change. How can I sort my arraylist?
package org.stocktwits.model;
import java.io.Serializable;
import java.text.DecimalFormat;
public class Quote implements Serializable {
private static final long serialVersionUID = 1L;
public String symbol;
public String name;
public String change;
public String percentChange;
public String open;
public String daysHigh;
public String daysLow;
public String dividendYield;
public String volume;
public String averageDailyVolume;
public String peRatio;
public String marketCapitalization;
public String yearHigh;
public String yearLow;
public String lastTradePriceOnly;
public DecimalFormat df = new DecimalFormat("#,###,###,###,###,##0.00");
public DecimalFormat vf = new DecimalFormat("#,###,###,###,###,##0");
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getChange() {
return change;
}
public void setChange(String change) {
if(change.equals("null")){
this.change = "N/A";
}
else{
float floatedChange = Float.valueOf(change);
this.change = (df.format(floatedChange));
}
}
public String getPercentChange() {
return percentChange;
}
public void setPercentChange(String percentChange) {
if(percentChange.equals("null"))
percentChange = "N/A";
else
this.percentChange = percentChange;
}
public String getOpen() {
return open;
}
public void setOpen(String open) {
if(open.equals("null"))
this.open = "N/A";
else
this.open = open;
}
public String getDaysHigh() {
return daysHigh;
}
public void setDaysHigh(String daysHigh) {
if(daysHigh.equals("null"))
this.daysHigh = "N/A";
else{
float floatedDaysHigh = Float.valueOf(daysHigh);
this.daysHigh = (df.format(floatedDaysHigh));
}
}
public String getDaysLow() {
return daysLow;
}
public void setDaysLow(String daysLow) {
if(daysLow.equals("null"))
this.daysLow = "N/A";
else{
float floatedDaysLow = Float.valueOf(daysLow);
this.daysLow = (df.format(floatedDaysLow));
}
}
public String getVolume() {
return volume;
}
public void setVolume(String volume) {
if(volume.equals("null")){
this.volume = "N/A";
}
else{
float floatedVolume = Float.valueOf(volume);
this.volume = (vf.format(floatedVolume));
}
}
public String getDividendYield() {
return dividendYield;
}
public void setDividendYield(String dividendYield) {
if(dividendYield.equals("null"))
this.dividendYield = "N/A";
else
this.dividendYield = dividendYield;
}
public String getAverageDailyVolume() {
return averageDailyVolume;
}
public void setAverageDailyVolume(String averageDailyVolume) {
if(averageDailyVolume.equals("null")){
this.averageDailyVolume = "N/A";
}
else{
float floatedAverageDailyVolume = Float.valueOf(averageDailyVolume);
this.averageDailyVolume = (vf.format(floatedAverageDailyVolume));
}
}
public String getPeRatio() {
return peRatio;
}
public void setPeRatio(String peRatio) {
if(peRatio.equals("null"))
this.peRatio = "N/A";
else
this.peRatio = peRatio;
}
public String getMarketCapitalization() {
return marketCapitalization;
}
public void setMarketCapitalization(String marketCapitalization) {
if(marketCapitalization.equals("null"))
this.marketCapitalization = "N/A";
else
this.marketCapitalization = marketCapitalization;
}
public String getYearHigh() {
return yearHigh;
}
public void setYearHigh(String yearHigh) {
if(yearHigh.equals("null"))
this.yearHigh = "N/A";
else
this.yearHigh = yearHigh;
}
public String getYearLow() {
return yearLow;
}
public void setYearLow(String yearLow) {
if(yearLow.equals("null"))
this.yearLow = "N/A";
else
this.yearLow = yearLow;
}
public String getLastTradePriceOnly() {
return lastTradePriceOnly;
}
public void setLastTradePriceOnly(String lastTradePriceOnly) {
if(lastTradePriceOnly.equals("null")){
this.lastTradePriceOnly = "N/A";
}
else{
float floatedLastTradePriceOnly = Float.valueOf(lastTradePriceOnly);
this.lastTradePriceOnly = (df.format(floatedLastTradePriceOnly));
}
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((change == null) ? 0 : change.hashCode());
result = prime * result
+ ((daysHigh == null) ? 0 : daysHigh.hashCode());
result = prime * result + ((daysLow == null) ? 0 : daysLow.hashCode());
result = prime
* result
+ ((lastTradePriceOnly == null) ? 0 : lastTradePriceOnly
.hashCode());
result = prime
* result
+ ((marketCapitalization == null) ? 0 : marketCapitalization
.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((open == null) ? 0 : open.hashCode());
result = prime * result + ((peRatio == null) ? 0 : peRatio.hashCode());
result = prime * result
+ ((percentChange == null) ? 0 : percentChange.hashCode());
result = prime * result + ((symbol == null) ? 0 : symbol.hashCode());
result = prime * result + ((volume == null) ? 0 : volume.hashCode());
result = prime * result
+ ((yearHigh == null) ? 0 : yearHigh.hashCode());
result = prime * result + ((yearLow == null) ? 0 : yearLow.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Quote other = (Quote) obj;
if (change == null) {
if (other.change != null)
return false;
} else if (!change.equals(other.change))
return false;
if (daysHigh == null) {
if (other.daysHigh != null)
return false;
} else if (!daysHigh.equals(other.daysHigh))
return false;
if (daysLow == null) {
if (other.daysLow != null)
return false;
} else if (!daysLow.equals(other.daysLow))
return false;
if (lastTradePriceOnly == null) {
if (other.lastTradePriceOnly != null)
return false;
} else if (!lastTradePriceOnly.equals(other.lastTradePriceOnly))
return false;
if (marketCapitalization == null) {
if (other.marketCapitalization != null)
return false;
} else if (!marketCapitalization.equals(other.marketCapitalization))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (open == null) {
if (other.open != null)
return false;
} else if (!open.equals(other.open))
return false;
if (peRatio == null) {
if (other.peRatio != null)
return false;
} else if (!peRatio.equals(other.peRatio))
return false;
if (percentChange == null) {
if (other.percentChange != null)
return false;
} else if (!percentChange.equals(other.percentChange))
return false;
if (symbol == null) {
if (other.symbol != null)
return false;
} else if (!symbol.equals(other.symbol))
return false;
if (volume == null) {
if (other.volume != null)
return false;
} else if (!volume.equals(other.volume))
return false;
if (yearHigh == null) {
if (other.yearHigh != null)
return false;
} else if (!yearHigh.equals(other.yearHigh))
return false;
if (yearLow == null) {
if (other.yearLow != null)
return false;
} else if (!yearLow.equals(other.yearLow))
return false;
return true;
}
}
If you (almost) always want to use that order you can add the Comparable interface to Quote and implement a compareTo method.
public int compareTo(Quote quote) {
int result = this.getName().compareTo(quote.getName());
if (result == 0) {
result = this.getChange().compareTo(quote.getChange());
}
if (result == 0) {
result = this.getPercentChange().compareTo(quote.getPercentChange());
}
return result;
}
Then use a sorted collection, or sort a list, and the quotes will be sorted.
For ad hoc sorting, a separate, possibly anonymous, Comparator is better.
Everybody is right that you want to use Comparators. Extending on that idea, if you want to be able to sort on multiple criteria, then a class like this will work for you:
public class MultiComparator<T> implements Comparator<T> {
private List<Comparator<T>> comparators;
public MultiComparator(List<Comparator<T>> comparators) {
this.comparators = comparators;
}
public int compare(T o1, T o2) {
for (Comparator<T> comparator : comparators) {
int comparison = comparator.compare(o1, o2);
if (comparison != 0) return comparison;
}
return 0;
}
}
Then you just write really simple comparators for whichever fields you desire and you can combine them into more complex comparators more easily and with more reuse.
Have a look at the ComparatorChain from the Apache Commons Collection. This should do the job. Don't implement logic if is already available and tested.
At the following site I have a tutorial: Sorting Objects By Multiple Attributes"
Create an appropiate Comparator that will compare two items according to your desired criteria. Then use Collections.sort() on your ArrayList.
If at a later time you want to sort by different criteria, call Collections.sort() again with a different Comparator.
Sun has devoted big part of its tutorial to sorting in Java collections:
http://download.oracle.com/javase/tutorial/collections/interfaces/order.html
It discusses both Comparable and Comparator interfaces with examples.
See Collections.sort with an explicit Comparator (or the Collections.sort kind that requires the input to implement Comparable, if you prefer).
There are two things:
Sorting on multiple fields of an object
Multilevel sorting (Here sorting done on first field and then next sorting applied on grouping done on similar items in previous sort)
For #2: I found this below article very much close to what i desire
http://strangeoptics.blogspot.com/2011/09/sorting-objects-by-multiple-attributes.html