我的任務是讀取 2 個檔案并匹配檔案的內容并提供兩個檔案的不匹配條目串列。這意味著我必須顯示兩個檔案中有多少匹配的條目,檔案 1 中有多少不匹配的條目不在檔案 2 中,檔案 2 中有多少不匹配的條目不在檔案 1 中。
我的方法是讀取檔案,從中創建 java 物件,將 2 個檔案的內容放入 2 個單獨的陣列串列并進行比較。我當前的代碼如下所示。為了澄清起見,我想檢查物件的內容(例如:檢查 EmployeeID 并從兩個檔案中匹配)。
在下面的代碼中,我將 file1 的內容與 file2 匹配,并從 file2 中洗掉了匹配的內容。可以很好地匹配條目并獲得 file1 與 file2 相比的不匹配計數。
我計劃匹配 file2 中的剩余專案,并compareByEmpIdandDOB使用 fileTwoEmpList 作為第一個引數,fileOneEmpList 作為第二個引數,以相同的方法進行另一輪,得到 file2 與 file1 相比的不匹配計數。但我覺得這是一種矯枉過正而且效率不高的做法。有人可以指出不同的方法嗎?
兩個陣列串列都已排序。提前致謝 !
public class EmpMatching {
public void compareLists(List<EmployeeDetails> fileOneEmpList, List<EmployeeDetails> fileTwoEmpList){
Collections.sort(fileOneEmpList);
Collections.sort(fileTwoEmpList);
List<EmployeeDetails> unmatchedFromListTwo = compareByEmpIdandDOB(fileOneEmpList,fileTwoEmpList);
}
public List<EmployeeDetails> compareByEmpIdandDOB(List<EmployeeDetails> fileOneEmpList,List<EmployeeDetails> fileTwoEmpList){
int matchEmpCountFromTwoFiles = 0;
System.out.println("File One List Size Before Recon " fileTwoEmpList.size());
for(EmployeeDetails fileOneEmp : fileOneEmpList){
for(int index = 0;index < fileTwoEmpList.size();index ){
EmployeeDetails fileTwoEmp= fileTwoEmpList.get(index);
if(fileOneEmp.getEmpID().equals(fileTwoEmp.getEmpID()) && fileOneEmp.getEmpDOB().equals(fileTwoEmp.getEmpDOB())){
matchEmpCountFromTwoFiles ;
fileTwoEmpList.remove(fileTwoEmp);
System.out.println("Match Found " fileOneEmp.getEmpID());
}
}
System.out.println("File Two List Size " fileTwoEmpList.size());
}
System.out.println("Match Count >>>>> " matchEmpCountFromTwoFiles);
System.out.println("File Two List Size >>>>> " fileTwoEmpList.size());
return fileTwoEmpList;
}
}
//Model class
public class EmployeeDetails implements Comparable<EmployeeDetails>{
private String EmpID;
private String EmpName;
private String EmpDOB;
@Override
public int compareTo(EmployeeDetails o) {
return 0;
}
}
uj5u.com熱心網友回復:
您無需為此任務對這些串列進行排序。
就集合論而言,您需要找到集合差。即查找僅出現在第一個或第二個串列中的所有唯一物件。
這個任務可以用幾行具有線性時間復雜度的代碼來解決。但重要的是要equals/hashCode在EmployeeDetails.
public List<EmployeeDetails> compareLists(List<EmployeeDetails> fileOneEmpList,
List<EmployeeDetails> fileTwoEmpList) {
Set<EmployeeDetails> emp1 = new HashSet<>(fileOneEmpList);
Set<EmployeeDetails> emp2 = new HashSet<>(fileTwoEmpList);
emp1.removeAll(emp2);
emp2.removeAll(emp1);
emp1.addAll(emp2);
return new ArrayList<>(emp1);
}
上面的方法既是最有效的也是最簡單的。
如果您對 Streams API 感到滿意,您可以嘗試另一種方法并通過以下方式實作此方法:
public List<EmployeeDetails> compareLists(List<EmployeeDetails> fileOneEmpList,
List<EmployeeDetails> fileTwoEmpList) {
return Stream.of(new HashSet<>(fileOneEmpList), new HashSet<>(fileTwoEmpList)) // wrapping with sets to ensure uniqueness (if objects in the list are guaranteed to be unique - use lists instead)
.flatMap(Collection::stream)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream()
.filter(entry -> entry.getValue() == 1) // i.e. object appear only once either in the first or in the second list
.map(Map.Entry::getKey)
.collect(Collectors.toList()); // .toList(); for Java 16
}
基于流的解決方案的時間復雜度也是線性的。但正如我所說,第一個基于 Collections API 的解決方案更簡單,性能也稍高一些。
如果由于某種原因equals(),hashCode()在EmployeeDetails. 而且您無法控制此類,也無法更改它。然后您可以宣告一個包裝類并執行相同的操作。
以下是如何使用 Java 16 記錄創建包裝器的示例。方法equals()和hashCode()將由編譯器基于empId和生成empDob。
public record EmployeeWrapper(String empId, String empDob) {
public EmployeeWrapper(EmployeeDetails details) {
this(details.getEmpID(), details.empDOB);
}
}
基于和equals/hashCode的類的實作可能如下所示(另外,您可以使用 IDE 的工具來生成這些方法):EmployeeDetailsempIDempDOB
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EmployeeDetails that = (EmployeeDetails) o;
return empID.equals(that.empID) && empDOB.equals(that.empDOB);
}
@Override
public int hashCode() {
return Objects.hash(empID, empDOB);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/466853.html
下一篇:計算陣列中大于下一個元素的元素C
