如何使用多个排序条件对ArrayList进行排序?
我有一个包含Quote对象的数组列表。我希望能够按名称,变化和百分比变化按字母顺序排序。我如何排列我的数据列表?如何使用多个排序条件对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;
}
}
创建一个合适的Comparator
,它将根据您所需的标准比较两个项目。然后在你的ArrayList上使用Collections.sort()
。
如果稍后您想按不同标准排序,请使用不同的Comparator
再次拨打Collections.sort()
。
你能提供一个我的compare()方法可能是什么样子的例子吗? – 2010-09-13 22:37:03
@Sheehan该文档解释了合同。由您决定订购。想像它就像在图书馆看书,例如首先进入“小说”或“非小说类”部分,然后查找整个数字,然后查看小数点后的部分。你首先比较“更重要”的东西并不断缩小。如果一个更重要的部分多于另一个,则终止排序(因为您已经发现了更好的命令)。 – 2010-09-13 23:01:07
这个答案不适用于我,我有两列,首先我想排序基于列之一arraylist之后,我想排序在第二列,但它不能正常工作,我arraylist排序列两totaly! “对于临时排序,一个单独的,可能是匿名的比较器更好。” – 2016-12-13 11:57:45
Sun公司已经投入了教程的重要组成部分,以在Java集合排序:
http://download.oracle.com/javase/tutorial/collections/interfaces/order.html
它讨论了与实例都具有可比性和比较器接口。
如果您(几乎)总是希望使用该订单,则可以将Comparable界面添加到报价并实施compareTo方法。
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;
}
然后使用排序后的集合或对列表进行排序,然后对引号进行排序。
对于临时排序,单独的,可能是匿名的比较器更好。
+1 – user3437460 2015-06-16 20:32:55
大家都很对,你想用比较器。扩展上的想法,如果你希望能够进行排序多个标准,那么像这样的类会为你工作:
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;
}
}
然后你只需编写非常简单的比较无论哪个字段,你的愿望,你可以结合他们更容易更复杂的比较和更多的重用。
如果需要进行大量比较和性能问题,可以将私有List
同意,或者这个班可能是最终的。我差不多就是这么写的,以表达这个想法。在JDK中确实应该有类似的东西,如果它不在任何数量的集合库中,我会感到惊讶...... – romacafe 2010-09-13 23:01:06
这种比较器链接的复杂性是什么?每次我们链接比较器时,我们是否基本上排序?所以我们为每个比较器做一个n * log(n)操作? – 2015-11-10 16:53:24
查看Apache Commons Collection的ComparatorChain。这应该完成这项工作。如果已经可用并经过测试,则不要实施逻辑。
在下面的网站我有一个教程:Sorting Objects By Multiple Attributes"
+1 Thank you for this。不得不求助于第三方库,因为这是IMHO的一个Java编程语言的巨大缺点。我同意strangeoptics,不要在那里推出自己的实现是一个可以实现的库。直接链接到无依赖关系的ComparatorChain类:http://www.jarvana.com/jarvana/view/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1 -sources.jar!/org/apache/commons/collections/comparators/ComparatorChain.java – Moritz 2013-01-10 13:21:03
谢谢您关闭提供示例代码来演示这个概念。这(与您的文章相结合)是OP问题的绝佳答案。 – 2017-01-30 17:05:55
我真的很讨厌这样的类。类需要有真正的业务逻辑才值得 - 而我更喜欢沿着哈希线使用类似这样的东西。从长远来看,使用一个类作为一个属性包就会变得烦人。重复性应该表明它显然是错误的。有些人认为这是Java的错,我倾向于认为这是程序员不愿意分支出去的错。我已经以允许验证,类型安全和许多其他技巧的方式完成了这项工作。没有样板代码,但它有很多工作 - 尽管值得 - 样板很烂。 – 2010-09-13 22:25:28
不知道我完全同意,但有一件事情对我来说是突出的:有所有这些setter和getter方法,但他们获取/设置的字段都是公开的!那些应该是私人的。 – 2010-09-13 22:44:05