比较两个集合,比较两个文本文件的添加,删除和修改

时间:2012-03-19 08:00:29

标签: java file collections io

我有两个系列,如下所示,为学生提供ID。

ID是字符串,格式为111-1111。例如ids 221-2534,215-6365等

 Collection<String> newKeys = new ArrayList<String>();
 Collection<String> oldKeys = new ArrayList<String>();

ids与其他数据一起处于固定格式文件中。这是前8个char id,接下来10个char name,接下来10个char addr等等。

我正在将ids读入收藏中,如下所示:

String oldFile = "C:\\oldFile.dat";
String newFile = "C:\\newFile.dat";
BufferedReader in;
String str;
// Read keys from old file
in = new BufferedReader(new FileReader(oldFile));
while ((str = in.readLine()) != null) {
      oldKeys.add(str.substring(0, 8).trim());
}
in.close();

// Read keys from new file
in = new BufferedReader(new FileReader(newFile));
while ((str = in.readLine()) != null) {
    newKeys.add(str.substring(0, 8).trim());
}
in.close();   

此处文件中的条目在SSN上排序。所以我相信形成的收藏品也会被分类。

现在:

案例:我想通过比较两个集合来了解作为结果列表的差异。这就是我需要的列表,其中包含已添加的条目,已删除的条目以及相同的条目。

然后,我将使用具有公共条目的列表从两个文件中读取相应的数据,并将其与任何修改进行比较。

这是在我有了共同的清单之后 -

a)从列表中获取ID。从两个文件中读取此id的相应数据到字符串中。比较字符串的任何差异。如果存在差异,请将newFile String移动到fileWithUpdates。

b)如果没有差别,请不要做任何事情。

问题:

1)这是正确的做法吗?

2)此外,如何比较两个集合以获得结果列表即。 toBeDeleted,toBeAdded和sameEntries?

3)如何从密钥上的文件中读取特定行(在这种情况下为学生ID)?

更新

根据以下答案,添加以下代码:

Iterator<String> iOld = oldKeys.iterator();
    Iterator<String> iNew = newKeys.iterator();
    Map<String, String> tempMap = new HashMap<String, String>();

    while (iOld.hasNext()) {
        tempMap.put(iOld.next(), "old");
    }

    while (iNew.hasNext()) {
        String temp = iNew.next();
        if (tempMap.containsKey(temp)) {
            tempMap.put(temp, "both");
        }

        else {
            System.out.println("here");
            tempMap.put(temp, "new");
        }
    }

所以现在我有一张地图:

要比较的条目:以上地图中的条目值为“both”

要添加的条目:上面带有值“new”的地图中的条目

要删除的条目:上方地图中的条目值为“旧”

所以我的问题归结为:

如何从密钥上的文件中读取特定行,以便我可以比较它们进行数据修改?

感谢阅读!

4 个答案:

答案 0 :(得分:1)

总的来说,我不认为这是正确的做法。我不是将所有信息存储在单个String中,而是创建一个对象,其中包含您需要存储的各种内容的字段。

public Student {
   String id; //or int, or char[8]
   String firstName, lastName;
   String address;
  //and so on

  //constructor - Given a line of input from the data file, create a Student object
  public Student(String line) {
     id = line.substring(0,8);
     //and so on

  }

至于比较两个集合,让我们将它们声明为ArrayLists,然后跟踪它们共同的索引。

ArrayList<String> newKeys = new ArrayList<>();  //java 7 syntax
ArrayList<String> oldKeys = new ArrayList<>();
//store keys from files.

TreeMap<Integer, Integer> commonKeys = new TreeMap<Integer, Integer>();
//stores the index values from newList as keys that get mapped to the old list index.

ArrayList<Integer> removedKeys =ArrayList<>();  
// Store the indices from oldKeys that are not in newKeys.

int newListIndex = 0;
int oldListIndex = 0;
while(newListIndex < newKeys.size() && oldListIndex<oldKeys.size()) {
   if(newKeys.get(newListIndex).equals(oldKeys.get(oldListIndex) ) {
      commonKeys.put(newListIndex,oldListIndex);
      oldListIndex++; newListIndex++ 
   }
   else if(newKeys.get(newListIndex).compareTo(oldKeys.get(oldListIndex)>0 ) {
      removedKeys.add(oldListIndex);
      oldListIndex++
   }
   else {
      //maybe this is a newListIndex that is not in the old list, so it was added.
      newListIndex++;
   }
}

您需要稍微调整上面的代码以使其具有故障安全性。另一种方法是使用这样的contains方法:

for(int i=0; i<oldKeys.size(); i++) {
   String oldKey = oldKeys.get(i);
   if(newKeys.contians(oldKey);
       commonKeys.put(newKeys.indexOf(oldKey) , i);
   else
       removedKeys.add(i);

}

答案 1 :(得分:0)

如果您的文件不是太大,也许您可​​以执行以下步骤

  • 创建HashMap
  • 对于旧文件中的每个条目,请使用值“旧”
  • 添加
  • 对于新文件中的每个条目,
    • 检查它是否在HashMap中
      • 如果是这样,那么设置值'Both'(另外,你可以将它添加到常用元素的HashMap中)
      • 如果没有,请添加值“新建”

这应该有希望解决问题2.如果有效,请告诉我。谢谢!

答案 2 :(得分:0)

你可以这样继续,

Collection<String> newKeys = new ArrayList<String>();  
Collection<String> oldKeys = new ArrayList<String>(); 

Collection<String> toBeDeleted = new ArrayList(oldKeys).removeAll(newKeys);
Collection<String> toBeAdded = new ArrayList(newKeys).removeAll(oldKeys);

Collection<String> sameEntries = new ArrayList(newKeys).removeAll(toBeAdded);

虽然对于第三个问题,如果你想保持键自动排序,你最好使用HashMap(或TreeMap)。

***更新

在原始文件阅读代码中,您可以进行以下更改,

Map<String, String> oldContentMap = new HashMap<String, String>();  
while ((str = in.readLine()) != null) {       
    oldKeys.add(str.substring(0, 8).trim()); 
    oldContentMap.put(str.substring(0, 8).trim(),str.substring(8).trim());
} 
in.close(); 

和新文件类似,

  Map<String, String> newContentMap = new HashMap<String, String>();  
    while ((str = in.readLine()) != null) {       
        newKeys.add(str.substring(0, 8).trim()); 
        newContentMap.put(str.substring(0, 8).trim(),str.substring(8).trim());
    } 
    in.close(); 

现在你可以继续进行比较了,

for (Map.Entry<String, String> entry : tempMap.entrySet()) { 
    if(entry.getValue().equals("both"){ //comparing for keys in both lists
         String oldContent = oldContentMap.get(entry.getKey());
         String newContent = newContentMap.get(entry.getKey());
         if(oldContent.equals(newContent)){
            System.out.println("Different data for key:"+entry.getKey());
         }
    }
}

你可以使用必要的临时变量并将声明移到循环外面。

答案 3 :(得分:0)

我会以这种方式完成你的任务

  • 为每个文件创建两个HashMap(oldFile,newFile),你的id将是地图的键
  • 构建新的arraylists:common,toBeAdded,toBeDeleted
  • 循环on oldKeysHashMap键:为每个键检查newHasMap中是否存在该键。如果是,请检查两个键是否包含相同的值(这对于地图来说很容易) - &gt;把这个条目放在共同的arraylist中。如果没有把条目放入toBeDeleted。
  • 在newKeysHashMap上循环并填写toBeAdded arrayList
  • 将toBeAdded和Common arraysList混合在一个新的。删除两个原始文件。编写一个新文件并使用新混合arrayList的条目填充该文件。 (删除和创建新文件应该比搜索文件中的ID并删除行更加轻松)

我还可以提供一些代码段。如果需要使用Map接口的实现来保持条目的排序。这不是HashMap的情况,SortedHashMap可能是正确的。