我需要一个TreeMap的比较器.我应该在我的TreeMap的构造函数中匿名写这个吗?我怎么能写我的比较器.目前,Java不喜欢我的代码(我可以匿名执行此操作吗?):
SortedMap<String, Double> myMap =
new TreeMap<String, Double>(new Comparator<Entry<String, Double>>()
{
public int compare(Entry<String, Double> o1, Entry<String, Double> o2)
{
return o1.getValue().compareTo(o2.getValue());
}
});
Run Code Online (Sandbox Code Playgroud)
我试图做一个最小堆1的longS IN C++使用STL make_heap等,但我比较似乎并不正确比较.以下是我目前的比较器:
struct greater1{
bool operator()(const long& a,const long& b) const{
return a>b;
}
};
Run Code Online (Sandbox Code Playgroud)
然而,当我std::pop_heap(humble.begin(),humble.end(),g);在那里g是一个实例greater1和humble一个堆谁使[9,15,15,25],当sort_heap被调用时,我得到一个15弹出.
我的比较器是否正确?可能出了什么问题?
编辑:
我意识到我正在运行没有比较器的sort_heap,而当我运行它这个比较器时,我得到[15,15,9,25]了sort_heap.现在我在想我的比较器肯定不起作用,但不确定原因.
1默认情况下,STL创建一个最大堆,所以我需要一个比较器.
我最近在SO聊天中看到了一个讨论,但没有明确的结论,所以我最后在那里问.
这是出于历史原因还是与其他语言的一致性?在查看compareTo各种语言的签名时,它会返回一个int.
为什么它不返回枚举.例如在C#中我们可以这样做:
enum CompareResult {LessThan, Equals, GreaterThan};
Run Code Online (Sandbox Code Playgroud)
并且:
public CompareResult CompareTo(Employee other) {
if (this.Salary < other.Salary) {
return CompareResult.LessThan;
}
if (this.Salary == other.Salary){
return CompareResult.Equals;
}
return CompareResult.GreaterThan;
}
Run Code Online (Sandbox Code Playgroud)
在Java中,枚举是在这个概念之后引入的(我不记得有关C#)但它可以通过额外的类来解决,例如:
public final class CompareResult {
public static final CompareResult LESS_THAN = new Compare();
public static final CompareResult EQUALS = new Compare();
public static final CompareResult GREATER_THAN = new Compare();
private CompareResult() {}
}
Run Code Online (Sandbox Code Playgroud)
和
interface Comparable<T> {
Compare compareTo(T obj);
}
Run Code Online (Sandbox Code Playgroud)
我问这个是因为我不认为一个int …
在Java 8中,@FunctionalInterface引入了注释以表示任何具有一个抽象方法作为功能接口的接口.引入它的原因之一是指示用户(程序员),lambda表达式可以在功能接口的上下文中使用.
该Comparator接口都被注解@FunctionalInterface.但是,两种方法都是抽象的.
int compare(T o1, T o2);
Run Code Online (Sandbox Code Playgroud)
和
boolean equals(Object obj);
Run Code Online (Sandbox Code Playgroud)
在文档中FunctionalInterface,它被明确提及为
从概念上讲,功能界面只有一种抽象方法.
这个equals方法不是被认为是抽象的吗?
我想TreeMap用Java 创建一个自定义排序顺序.需要根据第二个字符对作为字符串的排序键进行排序.值也是字符串.
示例地图:
Za,FOO
Ab,Bar
Run Code Online (Sandbox Code Playgroud) 如果我创建一个Comparator的单个实例,那么可以跨多个线程使用该实例来使用Collections.sort()对集合进行排序吗?或者,我是否需要为每次调用Collections.sort()创建一个新的Comparator实例以确保线程安全?
同时使用 Java 8 和 Java 11,请考虑以下TreeSet带有String::compareToIgnoreCase比较器的内容:
final Set<String> languages = new TreeSet<>(String::compareToIgnoreCase);
languages.add("java");
languages.add("c++");
languages.add("python");
System.out.println(languages); // [c++, java, python]
Run Code Online (Sandbox Code Playgroud)
当我尝试删除 中存在的确切元素时TreeSet,它起作用了:所有指定的元素都被删除:
languages.removeAll(Arrays.asList("PYTHON", "C++"));
System.out.println(languages); // [java]
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试删除而不是 中存在的更多TreeSet,则调用根本不会删除任何内容(这不是后续调用,而是调用而不是上面的代码段):
languages.removeAll(Arrays.asList("PYTHON", "C++", "LISP"));
System.out.println(languages); // [c++, java, python]
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?为什么会这样?
编辑:String::compareToIgnoreCase是一个有效的比较器:
(l, r) -> l.compareToIgnoreCase(r)
Run Code Online (Sandbox Code Playgroud) 一个Comparator在我使用我TreeMap打破了我的意图的行为TreeMap.看下面的代码:
TreeMap<String, String> treeMap = new TreeMap<>(new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.toLowerCase().compareTo(o2.toLowerCase());
}
});
treeMap.put("abc", "Element1");
treeMap.put("ABC", "Element2");
Run Code Online (Sandbox Code Playgroud)
我认为我所做的是我创建了一个按键排序的地图,不区分大小写.两个不同的元素具有不相等的键(abc和ABC),其比较将返回0.我期待这两个元素的随机排序.然而,命令:
System.out.println("treeMap: " + treeMap);
Run Code Online (Sandbox Code Playgroud)
导致:
treeMap: {abc=Element2}
Run Code Online (Sandbox Code Playgroud)
钥匙abc已重新分配价值Element2!
任何人都可以解释这是怎么发生的,如果它是一个有效的,记录在案的行为TreeMap?
我们上课吧Person.人有名字和身高.
Equals和hashCode()仅考虑名称.人是可比的(或者我们为它实施比较,无论哪一个).人员按身高进行比较.
期望两个不同的人可以具有相同高度的情况似乎是合理的,但是例如.TreeSet的行为类似于comapareTo()== 0表示等于,而不仅仅是相同的大小.
为了避免这种情况,如果大小相同,比较可以继续查看其他内容,但是它不能用于检测相同大小的不同对象.
例:
import java.util.Comparator;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
public class Person implements Comparable<Person> {
private final String name;
private int height;
public Person(String name,
int height) {
this.name = name;
this.height = height;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public String getName() {
return name;
}
@Override
public int compareTo(Person o) {
return Integer.compare(height, o.height);
}
public boolean equals(Object …Run Code Online (Sandbox Code Playgroud) 当我检查执行CaseInsensitiveComparator,这是私有内部类String,我发现奇怪的事情.
private static class CaseInsensitiveComparator
implements Comparator<String>, java.io.Serializable {
...
public int compare(String s1, String s2) {
int n1 = s1.length();
int n2 = s2.length();
int min = Math.min(n1, n2);
for (int i = 0; i < min; i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 != c2) {
c1 = Character.toUpperCase(c1);
c2 = Character.toUpperCase(c2);
if (c1 != c2) {
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
if (c1 != c2) {
// …Run Code Online (Sandbox Code Playgroud)