我有一组表示产品大小的字符串,其中大部分都是重复的,但不是名称。 (IE的大小至少有14种不同的拼写,每种拼写都需要保留。)我需要根据它们所代表的大小对它们进行排序。任何可能的小值都应该在任何可能的中值之前等。
我认为这是可能的唯一方法是实现一个特定的比较器,它包含不同的集合,它们根据它所代表的基本大小对每个大小进行分组。然后我可以通过确定特定大小落入哪个Set来实现-1,0,1关系。
有没有更强大的方法来实现这一目标?具体来说,我担心从现在开始的两个星期,当有人提出另一种拼写大的方法时。
编辑:要清楚它不是我有问题的实际比较器,它的设置包含每个组的集合。这是处理这种情况的正常方法吗?我如何对未来进行证明,以便每次添加新大小都不需要完全重新编译/部署?
答案 0 :(得分:1)
自定义比较器是解决方案。我不明白为什么你担心这不够强大。
答案 1 :(得分:1)
一种简单的方法是从resourcebundle加载大小别名。一些示例代码(将所有文件放在同一个包中):
封装size属性的接口
public interface Sized {
public String getSize();
}
产品类
public class Product implements Sized {
private final String size;
public Product(String size) {
this.size = size;
}
public String getSize() {
return size;
}
@Override
public String toString() {
return size;
}
}
实现神奇的比较器:
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
public class SizedComparator implements Comparator<Sized> {
// maps size aliases to canonical sizes
private static final Map<String, String> sizes = new HashMap<String, String>();
static {
// create the lookup map from a resourcebundle
ResourceBundle sizesBundle = ResourceBundle
.getBundle(SizedComparator.class.getName());
for (String canonicalSize : sizesBundle.keySet()) {
String[] aliases = sizesBundle.getString(canonicalSize).split(",");
for (String alias : aliases) {
sizes.put(alias, canonicalSize);
}
}
}
@Override
public int compare(Sized s1, Sized s2) {
int result;
String c1 = getCanonicalSize(s1);
String c2 = getCanonicalSize(s2);
if (c1 == null && c2 == null) {
result = 0;
} else if (c1 == null) {
result = -1;
} else if (c2 == null) {
result = 1;
} else {
result = c1.compareTo(c2);
}
return result;
}
private String getCanonicalSize(Sized s1) {
String result = null;
if (s1 != null && s1.getSize() != null) {
result = sizes.get(s1.getSize());
}
return result;
}
}
SizedComparator.properties:
1 = Small,tiny
2 = medium,Average
3 = Large,big,HUGE
单元测试(仅适用于快乐流程):
import org.junit.Before;
import org.junit.Test;
public class FieldSortTest {
private static final String SMALL = "tiny";
private static final String LARGE = "Large";
private static final String MEDIUM = "medium";
private Comparator<Sized> instance;
@Before
public void setup() {
instance = new SizedComparator();
}
@Test
public void testHappy() {
List<Product> products = new ArrayList<Product>();
products.add(new Product(MEDIUM));
products.add(new Product(LARGE));
products.add(new Product(SMALL));
Collections.sort(products, instance);
Assert.assertSame(SMALL, products.get(0).getSize());
Assert.assertSame(MEDIUM, products.get(1).getSize());
Assert.assertSame(LARGE, products.get(2).getSize());
}
}
请注意,ResourceBundles会自动缓存。您可以使用以下命令以编程方式重新加载ResourceBundle:
ResourceBundle.clearCache();
(自Java 1.6起)。或者,您可以使用一些Spring magic来创建自动重新加载消息资源。
如果从摇摇晃晃的属性文件中读取不够酷,您也可以很容易地将大小别名保存在数据库中。
答案 2 :(得分:0)
对字符串集合(或一般对象)强制执行任意排序,执行此操作的标准方法是按照您的建议实现Comparator。
除了您建议的“手动”解决方案之外,您可以考虑将字符串的相对edit distance与规范示例进行比较。这将是更多灵活的,因为它将适用于您没有想到的替代品。但就所涉及的工作而言,它可能对你的申请来说太过分了。