在多个独立的hashMap对象中搜索特定的键 [英] searching for specific keys in multiple independent hashMap objects

查看:111
本文介绍了在多个独立的hashMap对象中搜索特定的键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个稍微理论上的问题,我想在我开始编程我的解决方案之前进行清理......

背景。
我需要在两个MS Access文件之间进行比较。



每个文件都应该包含在其他文件中找到的数据。 / p>

由于我在JDBC中遇到的限制以及连接到Access结果集(它们只能向前滚动!)我创建了'java对象'(类)模拟结果集的结构。

本质上是
我有一个对象可以模拟结果集中的单个记录行(让我们称它为rowSet)
resSet对象然后有一个rowSets的'数组'。

然而,为了加快速度,我捕获了键和索引列中的值并创建'key_Index'的hashMap到相关的rowSet对象。



然后我做了比较。



取第一个resSet对象(用作主),从中收集个人的Key_Index hashmaps(让我们称之为'aKey'...。

现在使用thi s'aKey'对象来搜索其他可用的resSet对象,并查看是否有包含与'aKey'中的值匹配的key_Index的值。

然而,我有只是有一个相当恼人的想法。

如果我使用代码
resSet.get(aKey)
对其中一个resSet对象将我因为'aKey'对象显然不是同一个对象 - 虽然它的内容应该是相同的(即可比较的)。



我不得不说,因为我阅读我的问题,我认为它措辞不好......所以我想我会包括我创建的类的副本......



重要部分:

成员:
挑战 - '结果集'类型对象的数组列表。



方法:
runChallenge()

  package KWhite; 

/ **
* RScomparator设计用于比较双输入数据库系统的实例,因为经常在本地运行医学试验数据中发生
*。
*
*双重入口是为了确保在输入过程中没有错误,在单独的独立实例中执行
*。 RScolmparator对象特别能够将任意
*个结果集作为其输入(即来自多个独立创建的数据库的查询)
*
*应该认识到,该对象应该可能是称为DBcomparator
*对象的一部分。
*
* /
//在此处导入

//导入记录器类和所需的依赖关系...
import java.util.ArrayList;
import java.util.HashMap;

导入org.apache.log4j.PropertyConfigurator;

导入MrBlue.DB_Table;
导入TawuaiLogger.tawuaiLogger;

public class RScomparator {

//静态变量

//记录器实例
private static final TawuaiLogger.tawuaiLogger errLog = new tawuaiLogger( RScomparator);

//类成员变量

/ **这是ResSet对象的一个​​选择,它将对数据提出挑战* /
private ArrayList< ResSet_KW>挑战;
/ **被挑战的当前表的名称* /
private String tableName;
/ **用于元数据参考的'table'对象,这可以用于获取列类型等* /
私有DB_Table表;

//这些是我们的报表对象
/ **挑战失败的报表数组* /
private ArrayList< report_KW>失败;
/ **一个错误报告数组,即没有能够创建的挑战者,没有找到等价值* /
private ArrayList< report_KW>错误;
/ **好值的报表数组* / b $ b private ArrayList< report_KW>成功;

/ **这是主类或构造函数
*
*如果它是一个构造函数重命名以反映类的名称
* @param args
* /
public RScomparator(DB_Table t)// TODO根据需要添加参数
{
PropertyConfigurator.configure(Log4j.properties);
// TODO自动生成的方法存根
challenge = new ArrayList< ResSet_KW>();
//为这个挑战场景初始化我们的报告对象
fail = new ArrayList< report_KW>();
errors = new ArrayList< report_KW>();
success = new ArrayList< report_KW>();
table = t;
tableName = t.getTblName();
}

//类方法在这里

/ **
*将结果集对象添加到此比较器中
*
* @param r将结果集对象插入到此挑战中。
*
* /
public void addChallenger(ResSet_KW r)
{
this.challenge.add(r);
}


/ **
*运行比较过程...
*尽管没有返回任何细节,但它会调用其他方法返回值
*
* /

public void runChallenge()
{
// TODO完成此方法,创建一个报告对象方式

//这些是将要比较的2个结果集对象
ResSet_KW gold = new ResSet_KW();
ResSet_KW silver = new ResSet_KW();



//确保挑战者列表中有对象。
if(challenge.size()<2)
{
//它必须有2个对象..
errLog.add(3,没有可用的结果比较表+ this.tableName);
//我们应该创建报告对象。
this.errors.add(new report_KW(tableName));
//跳出该方法。
return;
}

//获取第一行数据

gold = challenge.get(0); //第一个结果集。

//对于结果集中的每一列,搜索其他字符中的同一个键。
for(HashMap< String,String> c:gold.getRS()。 keySet())
{// c是映射中的键值
//遍历挑战对象
for(int i = 1; i< challenge.size(); i ++ )//我们不想使用第一个元素,所以从1开始不是零
{
silver = challenge.get(i);
if(silver.hasKey(c))
{
//元数据引用的临时对象

//如果存在一场比赛
Column_KW a = gold.getRS()。get(c);
Column_KW b = silver.getRS()。get(c);
//比较
a.compareTo(b,this.table);
//从比较中获取报告
(report_KW k:a.getFailure())
{
this.fail.add(k);

for(report_KW k:a.getPassed())
{
this.success.add(k);

for(report_KW k:a.getPassed())
{
this.errors.add(k);
}
}
else
{
break; //返回for循环中的下一项
}
}
}









}


/ **
*创建错误消息创建器的助手方法
* @param附加消息(如果有的话)
* @返回完整消息
* /
private String getErrMessage(String m){
//当前stact trace中的第三个元素应该是调用方法
StackTraceElement caller = Thread.currentThread()。getStackTrace() [3];
String s = m +\ call from line+ caller.getLineNumber()
+\\\
method:+ this.getClass()+。 + caller.getMethodName();
return s;
}
} //结束类别

ps。任何coments我的代码或更多,欢迎

预先感谢

David



编辑:
我刚刚发现这个问题,嵌套的地图或java中的组合键是这将是我的解决方案,创建一个'定制'key_Index对象,然后定义一个hashcode()并等于它的对象。然而,我已经为我的key_index对象使用了一个'hashMap',那么这是否会在我未注意到的地方自动执行?

解决方案

<你说:
$ b


如果我在其他resSet对象之一上使用了代码resSet.get(aKey),
将会我有问题,因为'aKey'对象显然不是相同的
对象 - 虽然它的内容应该是相同的(即可比较)。




您必须分别执行 equals() hashcode() 。如果对象相等,实现 equals() hashcode()是不够的。 / p>

示例:

$ p $ import java.util.HashMap;
import java.util.Map;

class A {
字符串名称;
整数;
$ b $ public A(String name,Integer number){
super();
this.name = name;
this.number = number;
}

}

class B {
字符串名称;
整数;

public B(String name,Integer number){
super();
this.name = name;
this.number = number;
}

@Override
public boolean equals(Object obj){
if(obj instanceof B){
return obj == this || (name.equals(((B)obj).name)&& number.equals(((B)obj).number));
}
返回false;
}

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



public class TestHashMap {

public static void main(String ... args){
A a1 = new A(a,1);
A anotherA1 = new A(a,1);

地图< A,String> as = new HashMap< A,String>();

as.put(a1,a1);

System.out.println(as.get(anotherA1)); // print null

B b1 = new B(b,1);
B anotherB1 = new B(b,1);

地图< B,String> bs = new HashMap< B,String>();

bs.put(b1,b1);

System.out.println(bs.get(anotherB1)); //打印b1

}

}


I have a slightly theoretical question that I want to clear up before I start programing my solution any further...

Background. I need to perform comparisons between 2 (or possible more) MS Access files.

Each file should contain data that is found in one of the others.

Due to the 'limitation' I have encountered with JDBC and connecting to Access result sets (they are only forward scrollable!) I have created 'java objects' (classes) that models the structure of a result set.

in essence I have an object that models a single record line in the result set (lets call it a rowSet) A resSet object then has an 'array' of rowSets.

However to 'speed things up' I catch the values in the key and index columns and create a hashMap of 'key_Index' this to the relevant rowSet object.

Me comparison then does the following.

take the first resSet object (to use as the master), from this collect the individual the Key_Index hashmaps (lets call it 'aKey'....

Now use this 'aKey' object to search into the other avalailable resSet objects and see if any contain a value of a key_Index that matches the values in 'aKey'.

However I have just had a rather annoying thought.

If I use the code resSet.get(aKey) on one of my other resSet objects will I have problems as the 'aKey' object is obviously not the same object - although it's contents should be the same (ie comparable).

I have to say that as I read my question I think it is not well worded... so I think I will include a copy of the class that I have created...

The important parts:

members: challenge - an arrayList of 'result set' type objects.

method: the runChallenge()

package KWhite;

/**
 * the RScomparator is designed for the instance of comparing a double entry database system, as
 * often occurs in localy run medical trials data.
 * 
 * The double entry is to ensure that there are no errors made during input, the entry is performed
 * in separate independant instances. The RScolmparator object is specifically able to take any
 * number of result sets as its input (ie queries from multiple independantly created databases)
 * 
 * It should be recognised that this object should probably be called as part of a DBcomparator
 * object.
 * 
 */
//imports here

//import of logger class and required dependencies...
import java.util.ArrayList;
import java.util.HashMap;

import org.apache.log4j.PropertyConfigurator;

import MrBlue.DB_Table;
import TawuaiLogger.tawuaiLogger;

public class RScomparator {

//Static variables

//the logger instance
private static final TawuaiLogger.tawuaiLogger errLog = new tawuaiLogger("RScomparator");

//class member variables

/** this is a selection of ResSet objects that are going to have thier data challenged */
private ArrayList<ResSet_KW> challenge;
/**the name of the current table being challenged*/
private String tableName;
/**a 'table' object for meta data reference purposes, this can be used for getting column types etc */
private DB_Table table;

//These are our report objects
/**a report array for challenge failures */
private ArrayList<report_KW> fail;
/**a report array for errors, ie no challenger able to be made, no equivalent value found */
private ArrayList<report_KW> errors;
/**a report array for the good values */
private ArrayList<report_KW> success;

/** this is either the main class or the constructor
 * 
 * If it is a constructor rename to reflect the name of the class
 * @param args
 */
public RScomparator(DB_Table t) //TODO add arguments as required
{
    PropertyConfigurator.configure("Log4j.properties");
    // TODO Auto-generated method stub
    challenge = new ArrayList<ResSet_KW>();
    //initialise our report objects for this challenge scenario
    fail =  new ArrayList<report_KW>();
    errors = new ArrayList<report_KW>();
    success = new ArrayList<report_KW>();
    table = t;
    tableName = t.getTblName();
}

//class methods go here

/**
 * add a result set object into this comparator
 * 
 * @param r the result set object being inserted into this challenge.
 * 
 */
public void addChallenger(ResSet_KW r)
{
this.challenge.add(r);  
}


/**
 * this runs the comparison process...
 * Although no details in of itself are returned it calls other methods that do return a value
 *
 */

public void runChallenge()
{
//TODO finish this method, creating a report object on the way

    //these are the 2 result set objects that will be compared
    ResSet_KW gold = new ResSet_KW  ();
    ResSet_KW silver = new ResSet_KW ();



    //ensure the challenger list has objects in it.
    if(challenge.size() < 2)
    {
        //it must have 2 objects..
        errLog.add(3, "there are no results available for comparison of table " + this.tableName);
        //either way we should create report object.
        this.errors.add( new report_KW(tableName));
        //break out of the method.
        return;
    }

    //get the first row of data

    gold = challenge.get(0);//the first result set.

    //for each column in the result set, perform a search for the same key in the others..
    for(HashMap<String, String> c : gold.getRS().keySet())
    {//c is the key value in the map
        //cycle over the challenge object
        for (int i=1; i<challenge.size(); i++)//we don't want to use the first element, so start from 1 not zero
        {
            silver = challenge.get(i);
            if (silver.hasKey(c))
            {
                //a temp object for meta data referencing

                //only get the actual result values if there is a match
                Column_KW a = gold.getRS().get(c);
                Column_KW b = silver.getRS().get(c);
                //make the comparison
                a.compareTo(b, this.table);
                //get the reports from the comparison
                for(report_KW k :a.getFailure())
                    {
                    this.fail.add(k);
                    }
                for(report_KW k :a.getPassed())
                {
                    this.success.add(k);
                }
                for(report_KW k :a.getPassed())
                {
                this.errors.add(k);
                }
            }
            else
            {
                break;//return to the next item in the for loop
            }
        }
    }









}


/**
 *a helper method to create the error message creator
 *@ param m the extra message if any, 
 *@return s the full message
 */
private String getErrMessage(String m) {
    //the third element in the current stact trace should be the calling method
    StackTraceElement caller = Thread.currentThread().getStackTrace()[3];
    String s = m + "\ncalled from line " + caller.getLineNumber()
            + "\nmethod: " + this.getClass() + "." + caller.getMethodName();
        return s;
    }
}//end class

ps. any coments on my code or more that welcome

Thanks in advance

David

edit: I just found this question, Nested Maps or combined keys in java is this going to be my solution, create a'custom' key_Index object and then define a hashcode() and equals object for it. However I am allready using a 'hashMap' for my key_index object, so does this perform this automatically somewhere that I haven' noticed?

解决方案

You said :

If I use the code resSet.get(aKey) on one of my other resSet objects will I have problems as the 'aKey' object is obviously not the same object - although it's contents should be the same (ie comparable).

You have to implement equals() and hashcode() respectively. It is not enough to implement equals(), hashcode() must be the same if the objects are equal.

Example:

import java.util.HashMap;
import java.util.Map;

class A {
    String name;
    Integer number;

    public A(String name, Integer number) {
    super();
    this.name = name;
    this.number = number;
    }

}

class B {
    String name;
    Integer number;

    public B(String name, Integer number) {
    super();
    this.name = name;
    this.number = number;
    }

    @Override
    public boolean equals(Object obj) {
    if (obj instanceof B) {
        return obj == this || (name.equals(((B) obj).name) && number.equals(((B) obj).number));
    }
    return false;
    }

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

public class TestHashMap {

    public static void main(String... args) {
        A a1 = new A("a", 1);
        A anotherA1 = new A("a", 1);

        Map<A, String> as = new HashMap<A, String>();

        as.put(a1, "a1");

        System.out.println(as.get(anotherA1)); // prints null

        B b1 = new B("b", 1);
        B anotherB1 = new B("b", 1);

        Map<B, String> bs = new HashMap<B, String>();

        bs.put(b1, "b1");

        System.out.println(bs.get(anotherB1)); // prints b1

    }

}

这篇关于在多个独立的hashMap对象中搜索特定的键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆