2015-11-02 73 views
3

我有兩個列表。一個我從數據庫創建,一個來自Csv文件。現在我想收集包含數據庫和csv文件的列表中的記錄。我寫了這樣的代碼下面如何在anyMatch中應用複合BiPredicate()java 8 streams

BiPredicate<Trainee, Trainee> sameTrainee = (dbTrainee, csvTrainee) -> { 

    String dbTraineeFirstName = dbTrainee.getFirstName(); 
    String dbTraineeLastName = dbTrainee.getLastName(); 
    String dbTraineeEmail = dbTrainee.getEmail(); 
    LocalDateTime dbTraineeCompletionDate = dbTrainee.getSessionDateTime(); 
    String text = dbTraineeCompletionDate.format(DATE_TIME_FORMATTER); 
    LocalDateTime dbTraineeSessionDateTime = LocalDateTime.parse(text); 
    String dbTraineePhoneNumber = dbTrainee.getPhoneNumber(); 
    String dbTraineeSsn = dbTrainee.getSocialSecurityLastFour(); 
    String dbTraineeStreetOne = dbTrainee.getStreetOne(); 
    String dbTraineeCity = dbTrainee.getCity(); 

    String csvTraineeFirstName = csvTrainee.getFirstName(); 
    String csvTraineeLastName = csvTrainee.getLastName(); 
    String csvTraineeEmail = csvTrainee.getEmail(); 
    LocalDateTime csvTraineeSessionDateTime = csvTrainee.getSessionDateTime(); 
    String csvTraineePhoneNumber = csvTrainee.getPhoneNumber(); 
    String csvTraineeSsn = csvTrainee.getSocialSecurityLastFour(); 
    String csvTraineeStreetOne = csvTrainee.getStreetOne(); 
    String csvTraineeCity = csvTrainee.getCity(); 

    int dbTraineeSsnLength = dbTraineeSsn.length(); 
    int csvTraineeSsnLength = csvTraineeSsn.length(); 

    if (dbTraineeSsnLength != csvTraineeSsnLength) { 
     if (dbTraineeSsnLength == 4 && dbTraineeSsn.startsWith("0")) { 
      String dbTraineeSsnLast3Digits = dbTraineeSsn.substring(dbTraineeSsn.length() - 3); 
      if (csvTraineeSsnLength == 3 && csvTraineeSsn.endsWith(dbTraineeSsnLast3Digits)) { 
       csvTraineeSsn = "0" + csvTraineeSsn; 
      } 
     } 
    } 

    return dbTraineeFirstName.equals(csvTraineeFirstName) 
      && dbTraineeLastName.equals(csvTraineeLastName) 
      && dbTraineeEmail.equals(csvTraineeEmail) 
      && dbTraineeSessionDateTime.equals(csvTraineeSessionDateTime) 
      && dbTraineePhoneNumber.equals(csvTraineePhoneNumber) 
      && dbTraineeSsn.equals(csvTraineeSsn) 
      && dbTraineeStreetOne.equals(csvTraineeStreetOne) 
      && dbTraineeCity.equals(csvTraineeCity); 
}; 

,並要求它像

List<Trainee> foundInBothList = dbMonthlyTraineeList.stream() 
        .filter(dbTrainee -> csvTraineeList.stream() 
         .anyMatch(csvTrainee -> { 
          return sameTrainee.test(dbTrainee, csvTrainee); 
         }) 
        ).collect(Collectors.toList()); 

List<Trainee> notInFileList = dbMonthlyTraineeList.stream() 
        .filter(dbTrainee -> csvTraineeList.stream() 
         .noneMatch(csvTrainee -> { 
          return sameTrainee.test(dbTrainee, csvTrainee); 
         }) 
        ).collect(Collectors.toList()); 

它工作正常。但是因爲我的BiPredicate變得漫長而不整潔。所以我做了一個類,並收集在一個集合中的所有謂詞像下面

public class PlcbMonthlyReportStatisticsBiPredicates { 

    public static BiPredicate<Trainee, Trainee> isValidFirstName() { 
     return (dbTrainee, csvTrainee) -> { 
      String dbTraineeFirstName = dbTrainee.getFirstName(); 
      String csvTraineeFirstName = csvTrainee.getFirstName(); 
      return dbTraineeFirstName.equals(csvTraineeFirstName); 
     }; 
    } 

    public static BiPredicate<Trainee, Trainee> isValidSsn() { 
     return (dbTrainee, csvTrainee) -> { 
      String dbTraineeSsn = dbTrainee.getSocialSecurityLastFour(); 
      String csvTraineeSsn = csvTrainee.getSocialSecurityLastFour(); 
      ... 
      return dbTraineeSsn.equals(csvTraineeSsn); 
     }; 
    } 

    .... 

    public static List<BiPredicate<Trainee, Trainee>> getAllBiPredicates() { 

     List<BiPredicate<Trainee, Trainee>> allPredicates = Arrays.asList(
       isValidFirstName(), 
       isValidSsn(), 
       ... 
     ); 
     return allPredicates; 
    } 
} 

現在我收集所有的謂語,但我怎麼能在我的anyMatch()和noneMatch()應用這些謂詞。我試過這個,但是資源變得錯誤

List<Trainee> foundInBothList1 = dbMonthlyTraineeList.stream() 
    .filter(dbTrainee -> csvTraineeList.stream() 
     .anyMatch(csvTrainee -> { 
      List<BiPredicate<Trainee, Trainee>> allBiPredicates = getAllBiPredicates(); 
      return allBiPredicates.stream().reduce(BiPredicate::and).orElse((x,y)->true); //error 

     }) 
    ).collect(Collectors.toList()); 

我該如何應用這個。我的方法是對的嗎?

**編輯


@Entity 
public class Trainee { 

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); 

    private LocalDateTime sessionDateTime; 
    private String firstName; 
    .... 

    @Override 
    public boolean equals(Object otherObject) { 

     // Are the same? 
     if (this == otherObject) { 
      return true; 
     } 
     // Is otherObject a null reference? 
     if (otherObject == null) { 
      return false; 
     } 
     // Do they belong to the same class? 
     if (this.getClass() != otherObject.getClass()) { 
      return false; 
     } 

     // Get the reference of otherObject in a otherTrainee variable 
     Trainee otherTrainee = (Trainee)otherObject; 

     LocalDateTime dbTraineeCompletionDate = this.getSessionDateTime(); 
     String text = dbTraineeCompletionDate.format(DATE_TIME_FORMATTER); 
     LocalDateTime dbTraineeSessionDateTime = LocalDateTime.parse(text); 

     String dbTraineeSsn = this.socialSecurityLastFour; 
     String csvTraineeSsn = otherTrainee.getSocialSecurityLastFour(); 

     int dbTraineeSsnLength = dbTraineeSsn.length(); 
     int csvTraineeSsnLength = csvTraineeSsn.length(); 

     if (dbTraineeSsnLength != csvTraineeSsnLength) { 
      if (dbTraineeSsnLength == 4 && dbTraineeSsn.startsWith("0")) { 
       String dbTraineeSsnLast3Digits = dbTraineeSsn.substring(dbTraineeSsn.length() - 3); 
       if (csvTraineeSsnLength == 3 && csvTraineeSsn.endsWith(dbTraineeSsnLast3Digits)) { 
        csvTraineeSsn = "0" + csvTraineeSsn; 
       } 
      } 
     } 

     boolean isEqual = (this.firstName.equals(otherTrainee.firstName) 
      && this.lastName.equals(otherTrainee.lastName) 
      && this.email.equals(otherTrainee.email) 
      && dbTraineeSessionDateTime.equals(otherTrainee.sessionDateTime) 
      && this.phoneNumber.equals(otherTrainee.phoneNumber) 
      && dbTraineeSsn.equals(csvTraineeSsn) 
      && this.streetOne.equals(otherTrainee.streetOne) 
      && this.city.equals(otherTrainee.city) 
     ); 

     return isEqual; 
    } 

    @Override 
    public int hashCode() { 

     int hash = 37; 
     int code = 0; 

     code = (firstName == null ? 0 : firstName.hashCode()); 
     hash = hash * 59 + code; 

     code = (lastName == null ? 0 : lastName.hashCode()); 
     hash = hash * 59 + code; 

     code = (email == null ? 0 : email.hashCode()); 
     hash = hash * 59 + code; 

     code = (sessionDateTime == null ? 0 : sessionDateTime.hashCode()); 
     hash = hash * 59 + code; 

     code = (phoneNumber == null ? 0 : phoneNumber.hashCode()); 
     hash = hash * 59 + code; 

     code = (socialSecurityLastFour == null ? 0 : socialSecurityLastFour.hashCode()); 
     hash = hash * 59 + code; 

     code = (streetOne == null ? 0 : streetOne.hashCode()); 
     hash = hash * 59 + code; 

     code = (city == null ? 0 : city.hashCode()); 
     hash = hash * 59 + code; 

     return hash; 

    } 
} 

編輯2 (overridng hascode()和equals()之後)------------------ -------------------------------

發現在兩個:

發現在數據庫但不是CSV

List<Trainee> notInCsvFileList1 = dbMonthlyTraineeList.stream() 
    .filter(dbTrainee -> csvTraineeList.stream() 
     .noneMatch(csvTrainee -> { 
      return allBiPredicates.stream().reduce(BiPredicate::and).orElse((x,y)->true).test(dbTrainee, csvTrainee); 
     }) 
    ).collect(Collectors.toList()); 

//find out that elements of dbMonthlyTraineeList which is not present in arraylist(csvTraineeList). 
List<Trainee> notInCsvFileList = new ArrayList<>(dbMonthlyTraineeList); 
notInCsvFileList.removeAll(csvTraineeList); 
+0

HHMM我雖然只是重寫equals和hashCode(),只是檢查list.contains(),但我想與流:) – Basit

回答

2

看起來你好像在想這件事。爲什麼不只是用sameTrainee雙謂詞代碼覆蓋equals? (不要忘記也覆蓋hashCode)。

執行此操作後,您可以使用保持Trainee S中的兩個列表:

Set<Trainee> foundInBothList = new HashSet<>(dbMonthlyTraineeList); 
foundInBothList.retainAll(new HashSet<>(csvTraineeList)); 

該解決方案是O(n),所以它會比你的解決方案,這是執行好了很多O(N²)。這是因爲contains操作是恆定時間在Set


但是,如果你真的想你的代碼編譯,你只需要調用test方法,你有錯誤:

return allBiPredicates.stream().reduce(BiPredicate::and) 
           .orElse((x,y)->true) 
           .test(dbTrainee, csvTrainee); 
+0

謝謝。實際上我對hascode()方法感到困惑。在重寫equals()之後,如同您對同一受訓者說的一樣,我將提供什麼是HashCode的有效實現?這就是爲什麼我沒有重寫哈希碼... – Basit

+1

@Basit看看[這個答案](http://stackoverflow.com/a/113600/1743880)正確覆蓋'hashCode'。 – Tunaki

+0

嗨,非常感謝。你可以檢查我的編輯是否正確覆蓋hashcode()和equals()。謝謝。 – Basit

相關問題