【问题标题】:Java - Array of Objects to HashSetJava - HashSet 的对象数组
【发布时间】:2011-07-09 10:50:11
【问题描述】:

我有以下数组:

private static Optreden[] optredens = {
            new Optreden("Editors", "Main Stage", 16, 0, 4),
            new Optreden("Empire of the Sun", "Pyramid Marquee", 23, 45, 5),
            new Optreden("Florence and the Machine", "Marquee", 18, 45, 3),
            new Optreden("The Specials", "Marquee", 13, 10, 5),
            new Optreden("Muse", "Main Stage", 19, 0, 5),
            new Optreden("Faithless", "Main Stage", 14, 30, 5),
            new Optreden("Absynthe Minded", "Pyramid Marquee", 21, 45, 5),
            new Optreden("Pink", "Main Stage", 20, 30, 2),
            new Optreden("Editors", "Marquee", 21, 20, 4),
            new Optreden("Faithless", "Pyramid Marquee", 19, 0, 5)
            };

Optreden 对象构造函数如下所示:

Optreden(name, stage, hour, minutes, rating);

现在,我必须创建一个 Optreden 对象的 HashSet,但它可能不包含重复的名称,所以当我打印 HashSet 时,它必须如下所示:

The Specials (Marquee, 13u10)--> *****
Empire of the Sun (Pyramid Marquee, 23u45)--> *****
Florence and the Machine (Marquee, 18u45)--> ***
Pink (Main Stage, 20u30)--> **
Muse (Main Stage, 19u)--> *****
Absynthe Minded (Pyramid Marquee, 21u45)--> *****
Editors (Main Stage, 16u)--> ****
Faithless (Main Stage, 14u30)--> *****

问题是,我无法编辑 Optreden 类,它只有一个构造函数和一个 toString 方法,没有 getName() getter。

我怎样才能做到这一点?谢谢。

【问题讨论】:

  • 用name作为key的Map怎么样?... 归根结底,HashSet就是一个HashMap,其key和value是同一个对象。
  • 这看起来更像是一个组织问题而不是技术问题,我们只能帮助您解决技术问题...例如,您可以继承 Optreden 吗?或者,如果所有其他方法都失败了,反射会忽略可见性,但会牺牲代码可读性、类型安全性和运行时性能。
  • 在我看来,你的 Optreden 类的设计(性能 - 如音乐 - 英语)是问题的来源。具有 getter、setter、equals() 和 hashcode 的兼容 javabean 设计将使您走得更远。例如鉴于您的要求是一个集合,您可以使用带有自定义比较器的 TreeSet 来实现您的目标。如果您所拥有的只是一个 toString() 方法,我会使用 String 构造函数为 Optreden 创建一个适当的 JavaBean。使用它来解析设计不良的原始类的 toString() 输出,并为 equals() 和 hashcode() 方法提供正确的实现。
  • 嗯,Rock Werchter 的组织者:D

标签: java arrays set


【解决方案1】:

它必须是 HashSet 吗?如果您乐于改用 TreeSet,请使用自定义比较器创建一个用于比较名称的比较器。类似的东西(未编译或测试!):

Comparator<Optreden> compareByName = new Comparator<Optreden>() {
    public int compare(Optreden a, Optreden b) {
        return getName(a).compareTo(getName(b));
    }
    private String getName(Optreden o) {
        String s = o.toString();
        return s.substring(0, (s.indexOf('(') - 1);
    }
}

Set<Optreden> optredensUniqueByName = new TreeSet<Optreden>(compareByName);
optredensUniqueByName.addAll(Arrays.asList(optredens));

【讨论】:

  • @maasg:谢谢。我们的解决方案几乎相同 - 我的可能稍微简洁一些,但您的解决方案快了两分钟!
【解决方案2】:

只要Optreden不是final类,你可以子类化它以在构造函数中捕获name并实现equals()hashcode()以使用name,如下:

public class MyOptreden extends Optreden
{
    private String name;

    public MyOptreden(String name, String stage, int hour, int minutes, int rating) {
        super(name, stage, hour, minutes, rating);
        this.name = name; // A capture name here
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof MyOptreden && ((MyOptreden) obj).name.equals(name);
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }
}

只要你在你的集合中只使用这个类的实例,它就可以工作。

您必须覆盖setName()(如果存在)以更新name

【讨论】:

    【解决方案3】:

    请看我的评论。在原始问题中给出的当前限制下,即只有一个构造函数和一个 toString() 方法可用,您可以使用有序集合(例如 TreeSet)和自定义 Comparator 实现来创建一个集合。然后,您的 Comparator 实现将使用唯一的访问器方法 Optreden.toString() 来解析组的名称。 例如

    class OptredenComparator implements Comparator<Optreden> {
    ...
    
     int compare(Optreden o1, Optreden o2) {
         // this is to illustrate the logic. Mind the nulls
         String name1 = o1.split("(")[0];
         String name2 = o2.split("(")[0];
         return name1.compareTo(name2);
     }
    ...
    }
    

    然后您可以创建一个TreeSet(new OptredenComparator) 并将您的 Optreden 实例添加到其中。

    我想强调的是,虽然这是对原始问题的回答,但需要解决的根本问题是用作数据容器的类的设计(Optreden)

    }

    【讨论】:

    • A) 你不应该在你的代码中回复toString() 输出。 B) 比较器对 Set 没有用 - 你需要 equals()。看我的回答
    • @Bohemian A) toString() 同意。我首先警告过该解决方案,但这就是 OP 作为访问该类的唯一工具所提供的。我假设无法访问创建对象的地方,否则,为什么不滚动你自己的课程呢? B)关于Comparator,这是一个有效的选项。请参阅[download.oracle.com/javase/6/docs/api/java/util/…
    猜你喜欢
    • 2015-01-30
    • 2017-10-29
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多