java 哈希图 'cannot be resolved'。可以执行方法但不能打印

java hash map 'cannot be resolved'. can execute methods but can't print

我有一个程序,其中一个散列图,以元组的形式作为键(代表从输入文件读取的句子)和一个整数(它在数据中被观察到的次数) 能够填充数据,但无法响应我打印其内容的尝试。它填充在下面代码的 'for' 循环中,并且在该片段的底部是它要打印的地方。

public static void main(String[] args) throws IOException 
{
    Ontology ontology = new Ontology();
    BufferedReader br = new BufferedReader(new FileReader("/home/matthias/Workbench/SUTD/2_January/learning_first-order_horn_clauses_from_web_text/reverb/code/input_data/Whosebug_test.txt"));
    Pattern p = Pattern.compile("'(.*?)'\('(.*?)',\s*'(.*?)'\)\.");
    String line;
    while ((line = br.readLine()) != null) 
    {
        Matcher m = p.matcher(line);
        if( m.matches() ) 
        {
            String verb    = m.group(1);
            String object  = m.group(2);
            String subject = m.group(3);
            ontology.addSentence( new Sentence( verb, object, subject ) );
        }
    }

    for( String joint: ontology.getJoints() )
    {
        for( Integer subind: ontology.getSubjectIndices( joint ) )
        {
            Sentence xaS = ontology.getSentence( subind );

            for( Integer obind: ontology.getObjectIndices( joint ) )
            {

                Sentence yOb = ontology.getSentence( obind );

                Sentence s = new Sentence( xaS.getVerb(),
                                           xaS.getObject(),
                                           yOb.getSubject() );

                //System.out.println( s );                
                ontology.numberRules( s ); 

            }
        }
    }
    for (Map.Entry<Sentence, Integer> entry : ontology.numberRules.entrySet()) 
    {
        System.out.println(entry.getKey()+" : "+entry.getValue());
    }     
}

以下文件的底部是实现哈希映射的地方。这也采用输入句子并在句子的主语和宾语中搜索重叠值。系统试图做的是通过从输入数据推断来学习 "rules",即 contains(vitamin c, oranges)prevents(scurvy, vitamin c) 会产生输出 prevents(scurvy, oranges),事实是,在我的测试数据中有许多相同的规则,所以我想跟踪它们被观察到的次数,同时也只存储唯一 "rule" 的一个副本。这就是哈希映射将句子存储为键并将整数(计数)存储为值的原因。

private List<Sentence> sentences = new ArrayList<>();
/*
 * The following maps store the relation of a string occurring
 * as a subject or object, respectively, to the list of Sentence
 * ordinals where they occur.
 */
private Map<String,List<Integer>> subject2index = new HashMap<>();
private Map<String,List<Integer>> object2index = new HashMap<>();

/*
 * This set contains strings that occur as both,
 * subject and object. This is useful for determining strings
 * acting as an in-between connecting two relations. 
 */
private Set<String> joints = new HashSet<>();

public void addSentence( Sentence s )
{

    // add Sentence to the list of all Sentences
    sentences.add( s );

    // add the Subject of the Sentence to the map mapping strings
    // occurring as a subject to the ordinal of this Sentence
    List<Integer> subind = subject2index.get( s.getSubject() );
    if( subind == null )
    {
        subind = new ArrayList<>();
        subject2index.put( s.getSubject(), subind );
    }
    subind.add( sentences.size() - 1 );

    // add the Object of the Sentence to the map mapping strings
    // occurring as an object to the ordinal of this Sentence
    List<Integer> objind = object2index.get( s.getObject() );
    if( objind == null )
    {
        objind = new ArrayList<>();
        object2index.put( s.getObject(), objind );
    }
    objind.add( sentences.size() - 1 );

    // determine whether we've found a "joining" string
    if( subject2index.containsKey( s.getObject() ) )
    {
        joints.add( s.getObject() );
    }
    if( object2index.containsKey( s.getSubject() ) )
    {
        joints.add( s.getSubject() );
    }
}

public Collection<String> getJoints()
{
    return joints;
}
public List<Integer> getSubjectIndices( String subject )
{
    return subject2index.get( subject );
}
public List<Integer> getObjectIndices( String object )
{
    return object2index.get( object );
}
public Sentence getSentence( int index )
{
    return sentences.get( index );
}

//map to store learned 'rules'
Map<Sentence, Integer> ruleCount = new HashMap<>();

//store data
public void numberRules(Sentence sentence) 
{
    if (!ruleCount.containsKey(sentence))
    {
        ruleCount.put(sentence, 0);
    }
    ruleCount.put(sentence, ruleCount.get(sentence) + 1);
}   

这是存储句子的对象。

public class Sentence 
{
private String verb;
private String object;
private String subject;
public Sentence(String verb, String object, String subject )
{
    this.verb = verb;
    this.object = object;
    this.subject = subject;
}

public String getVerb()
{
    return verb; 
}

public String getObject()
{
    return object; 
}

public String getSubject()
{
    return subject;
}

public String toString()
{
    return verb + "(" + object + ", " + subject + ").";
}

}

输入数据如下所示

'prevents'('scurvy','vitamin C').
'contains'('vitamin C','orange').
'contains'('vitamin C','sauerkraut').
'isa'('fruit','orange').
'improves'('health','fruit').

希望输出数据能告诉我,比如

prevents(scurvy, orange).      2
prevents(scurvy, sauerkraut).  4
improves(health, orange).      1

其中句子是哈希映射的键,整数是关联值,对应于该句子在数据中被观察到的次数。

我在你的 Ontology class 中没有看到 numberRules 成员。

也许您打算使用 ruleCount 成员,这是我在您的代码中看到的唯一 Map<Sentence, Integer> 类型的变量。

for (Map.Entry<Sentence, Integer> entry : ontology.ruleCount.entrySet()) 
{
    System.out.println(entry.getKey()+" : "+entry.getValue());
}  

关于 Hector 的评论,这是一个不同的问题。当您使用自定义 classes 之一作为 HashMap 中的键(在您的情况下为 Sentence class),您必须覆盖 equalshashCode。如果您不这样做,a.equals(b) 将仅在 a==b 时 return 为真,这可能不是您想要的行为。当两个比较句子的动词、宾语和主语分别相等时,您可能希望 a.equals(b) 到 return 为真。 hashCode 的实现方式应该是,如果 a.equals(b) 为真,则 a.hashCode() == b.hashCode().