如何在Java中为TreeSet中使用的StringBuffer类实现一个比较器?
我想为StringBuffer实现一个比较器,它比较StringBuffer并相应地添加到TreeSet。这纯粹是为了学习目的。我知道在Hasable集合中有一个可变对象是个坏主意。但这里的目的是如何为现有的Java StringBuffer类实现comparator,并使用它创建树集。 我现在的代码如下。代码不编译。请帮帮我。谢谢如何在Java中为TreeSet中使用的StringBuffer类实现一个比较器?,java,comparator,treeset,stringbuffer,Java,Comparator,Treeset,Stringbuffer,我想为StringBuffer实现一个比较器,它比较StringBuffer并相应地添加到TreeSet。这纯粹是为了学习目的。我知道在Hasable集合中有一个可变对象是个坏主意。但这里的目的是如何为现有的Java StringBuffer类实现comparator,并使用它创建树集。 我现在的代码如下。代码不编译。请帮帮我。谢谢 public class ComparatorExample { public class SbufferComparator implements C
public class ComparatorExample {
public class SbufferComparator implements Comparator<StringBuffer> {
@Override
public int compare(StringBuffer s1, StringBuffer s2) {
return s1.toString().compareTo(s2.toString());
}
}
public static void main(String[] args) {
StringBuffer one = new StringBuffer("one");
StringBuffer two = new StringBuffer("two");
StringBuffer three = new StringBuffer("three");
Set<StringBuffer> sb=new TreeSet<StringBuffer>(new SbufferComparator());
sb.add(one);
sb.add(two);
sb.add(three);
System.out.println("set before change: "+ sb);
one.append("onemore");
System.out.println("set After change: "+ sb);
}
}
公共类比较示例{
公共类SbufferComparator实现Comparator{
@凌驾
公共整数比较(StringBuffer s1、StringBuffer s2){
返回s1.toString().compareTo(s2.toString());
}
}
公共静态void main(字符串[]args){
StringBuffer one=新的StringBuffer(“一”);
StringBuffer二=新的StringBuffer(“二”);
StringBuffer三=新的StringBuffer(“三”);
设置sb=新树集(新的SbufferComparator());
某人加(一);
某人加(二);
某人加(三);
System.out.println(“更改前设置:+sb”);
一.附加(“一个或多个”);
System.out.println(“更改后设置:+sb”);
}
}
内部类SbufferComparator
必须是静态的,或者必须重构为顶级类
否则,需要构造一个封闭的对象实例:
ComparatorExample ce = new ComparatorExample();
SbufferComparator comparator = ce.new SbufferComparator();
将其保留为非静态内部类没有多大意义,因为它不使用其封闭类中的任何实例字段或方法。因此,将其设置为静态或顶级。内部类
SbufferComparator
必须是静态的,或者必须重构为顶级类
否则,需要构造一个封闭的对象实例:
ComparatorExample ce = new ComparatorExample();
SbufferComparator comparator = ce.new SbufferComparator();
将其保留为非静态内部类没有多大意义,因为它不使用其封闭类中的任何实例字段或方法。因此,将其设置为静态或顶级。您应该在一个单独的文件中创建comparator类,而不是在同一个类中,或者如果您希望将其保留在内部,则将其设置为静态
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class ComparatorExample {
private static class SbufferComparator implements Comparator<StringBuffer> {
@Override
public int compare(StringBuffer s1, StringBuffer s2) {
return s1.toString().compareTo(s2.toString());
}
}
public static void main(String[] args) {
StringBuffer one = new StringBuffer("one");
StringBuffer two = new StringBuffer("two");
StringBuffer three = new StringBuffer("three");
Set<StringBuffer> sb=new TreeSet<StringBuffer>(new SbufferComparator());
sb.add(one);
sb.add(two);
sb.add(three);
System.out.println("set before change: "+ sb);
one.append("onemore");
System.out.println("set After change: "+ sb);
}
}
import java.util.Comparator;
导入java.util.Set;
导入java.util.TreeSet;
公共类比较示例{
私有静态类SbufferComparator实现Comparator{
@凌驾
公共整数比较(StringBuffer s1、StringBuffer s2){
返回s1.toString().compareTo(s2.toString());
}
}
公共静态void main(字符串[]args){
StringBuffer one=新的StringBuffer(“一”);
StringBuffer二=新的StringBuffer(“二”);
StringBuffer三=新的StringBuffer(“三”);
设置sb=新树集(新的SbufferComparator());
某人加(一);
某人加(二);
某人加(三);
System.out.println(“更改前设置:+sb”);
一.附加(“一个或多个”);
System.out.println(“更改后设置:+sb”);
}
}
注意进口声明 您应该在一个单独的文件中创建comparator类,而不是在同一个类中,或者如果希望将其保持在内部,则应将其设置为静态
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class ComparatorExample {
private static class SbufferComparator implements Comparator<StringBuffer> {
@Override
public int compare(StringBuffer s1, StringBuffer s2) {
return s1.toString().compareTo(s2.toString());
}
}
public static void main(String[] args) {
StringBuffer one = new StringBuffer("one");
StringBuffer two = new StringBuffer("two");
StringBuffer three = new StringBuffer("three");
Set<StringBuffer> sb=new TreeSet<StringBuffer>(new SbufferComparator());
sb.add(one);
sb.add(two);
sb.add(three);
System.out.println("set before change: "+ sb);
one.append("onemore");
System.out.println("set After change: "+ sb);
}
}
import java.util.Comparator;
导入java.util.Set;
导入java.util.TreeSet;
公共类比较示例{
私有静态类SbufferComparator实现Comparator{
@凌驾
公共整数比较(StringBuffer s1、StringBuffer s2){
返回s1.toString().compareTo(s2.toString());
}
}
公共静态void main(字符串[]args){
StringBuffer one=新的StringBuffer(“一”);
StringBuffer二=新的StringBuffer(“二”);
StringBuffer三=新的StringBuffer(“三”);
设置sb=新树集(新的SbufferComparator());
某人加(一);
某人加(二);
某人加(三);
System.out.println(“更改前设置:+sb”);
一.附加(“一个或多个”);
System.out.println(“更改后设置:+sb”);
}
}
注意进口声明 由于以下几个原因,比较或存储缓冲区是危险的
StringBuffer
是不必要的线程安全的,基本上不推荐使用StringBuilder
。改用那个类StringBuffer
和StringBuilder
都是可变的,这意味着它们不能安全地插入到TreeSet
中,因为它们可以更改(例如,sb.insert(0,'z')
将使字符串以z
开头,从而更改任何后续比较的结果)因此,请断开树集
StringBuilder
就很简单了O(m log n)
其中m
是缓冲区长度,n
是树大小TreeSet
中。这将工作得更干净、更快,并避免出现危险的边缘情况,例如渲染树集
时出现故障
下面的示例演示了如何在
TreeSet
中使用可变对象(如缓冲区)打破所有期望:
public static void main(String[] args) {
TreeSet<StringBuilder> tree = new TreeSet<>(new Comparator<StringBuilder>() {
@Override
public int compare(StringBuilder one, StringBuilder two) {
return one.toString().compareTo(two.toString());
}});
char from = 'a', to = 'm'; // change to adjust map size
char holdChar = 'd'; // change holdChar to adjust error location
StringBuilder hold = null;
for(char c = from; c <= to; c++) {
StringBuilder sb = new StringBuilder().append(c).append(c).append(c);
tree.add(sb);
if(c == holdChar) {
hold = sb;
}
}
System.out.println(tree);
hold.insert(0, to);
for(char c = from; c <= to; c++) {
StringBuilder sb = new StringBuilder().append(c).append(c).append(c);
if(c == holdChar) {
sb.insert(0, to);
}
System.out.println("Tree contains "+sb+(tree.contains(sb) ? "" : " NOPE!!"));
}
System.out.println(tree);
}
更糟糕的是,由于底层的树结构,准确地找到哪些字段或找不到哪些字段取决于映射大小和错误点。使用从/
到
/holdChar
的值,您将看到任意不同的结果。尝试holdChar='f'代码>例如。出于以下几个原因,比较或存储缓冲区是危险的
StringBuffer
是不必要的线程安全的