2015-11-02 70 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

相关问题