使用流

时间:2015-06-10 13:43:03

标签: java-8 java-stream

我有从数据库中获取的学生列表。我将谓词应用于List并使用有效的无效学生对List进行分区。现在,对于无效的学生,我想生成Map作为键,并将错误消息作为值生成。因为我需要为每个学生生成报告。这就是我在做什么,但我不知道这是不是一个好方法,还是有更好的方法。

实际上在获得无效的学生名单之后,我正在尝试创建一个功能,但我认为代码变得混乱,可能有更好的方法来做到这一点。这就是我在做什么

private List<Predicate<OlccStudent>> getAllPredicates() {
    List<Predicate<OlccStudent>> allPredicates = Arrays.asList(
            isValidFirstName(),
            isValidMiddleInitial(),
            isValidLastName(),
            isValidStreetAddress(),
            isValidCity(),
            isValidState(),
            isValidZip(),
            isValidDateOfBirth(),
            isValidSsn(),
            isValidTestDate(),
            isValidTestAnswers(),
            isValidProviderCode(),
            isValidInstructorCode()
    );
    return allPredicates;
}

public Map<Boolean, List<OlccStudent>> getStudentsMap(List<OlccStudent> olccStudentsList) {

    List<Predicate<OlccStudent>> allPredicates = getAllPredicates();
    Predicate<OlccStudent> compositePredicate =  allPredicates.stream()
                             .reduce(w -> true, Predicate::and);

    Map<Boolean, List<OlccStudent>> studentsMap= olccStudentsList
                .stream()
                .collect(Collectors.partitioningBy(compositePredicate));

    return studentsMap;
}

public Map<OlccStudent, String> getInvalidStudentsMap(Map<Boolean, List<OlccStudent>> studentsMap) throws Exception {

    List<OlccStudent> invalidStudentsList = 
            studentsMap.entrySet()
             .stream()
             .filter(p -> p.getKey() == Boolean.FALSE)
             .flatMap(p -> p.getValue().stream())
             .collect(Collectors.toList());

    Function<List<OlccStudent>, Map<OlccStudent, String>> invalidStudentFunction = list ->  {

        Map<OlccStudent, String> invalidStudentsMap = new LinkedHashMap<>();

        list.forEach(student-> {
            String errorMessage = getStudentErrorMessage(student);
            invalidStudentsMap.put(student, errorMessage);  
        });

        return invalidStudentsMap;
    };

    Map<OlccStudent, String> invalidStudentsMap = invalidStudentFunction.apply(invalidStudentsList);
    return invalidStudentsMap;

    return null;
}

private String getStudentErrorMessage(OlccStudent student) {

    String firstName = student.getFirstName();
    String middleInitial = student.getMiddleInitial();
    String lastName = student.getLastName();
    String streetAddress = student.getStreetAddress();
    ....

    StringBuilder errorBuilder = new StringBuilder();

    //The predicate 'negate' method returns a predicate that represents the logical negation or opposite
    if (isValidFirstName().negate().test(student)) {
        String error = "Invalid FirstName: " + firstName;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidMiddleInitial().negate().test(student)) {
        String error = "Invalid Middle Initial: " + middleInitial;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidLastName().negate().test(student)) {
        String error = "Invalid LastName: " + lastName;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidStreetAddress().negate().test(student)) {
        String error = "Invalid StreetAddress: " + streetAddress;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }
     ...

    if (errorBuilder.length() > 0) {
        errorBuilder.deleteCharAt(errorBuilder.length() - 1);
    } 

    return errorBuilder.toString().trim();
}

实际上,我对getStudentErrorMessage()中呼叫的list.forEach()感到困惑。我知道收藏家为您提供Collectors.joining功能。实际上我想以谓词的方式做到这一点。就像我创建了所有谓词的列表,然后在流中使用它。我可以用我的错误消息做类似的事情吗?就像我从invalid students List创建流,并使用Collectors.toMap()一样,将我的学生作为键和错误消息作为其值。

由于

修改 ----------------

public class OlccStudentPredicate {

    public static Predicate<OlccStudent> isValidTestDate() {
        return p -> isValidDate(p.getTestDate());
    }

    public static Predicate<OlccStudent> isValidDateOfBirth() {
        return p -> isValidDate(p.getDateOfBirth());
    }

    ...

    private static boolean isValidDate(String date) {
    boolean valid = false;
    if (StringUtils.isNotBlank(date)) {
        try {
            LocalDate.parse(date, DateTimeFormatter.ofPattern("MM/dd/yyyy"));
            valid = true;
        } catch (DateTimeParseException e) {

        }
    } 
    return valid;
}


@Test
public void test() {

    List<OlccStudent> olccStudentsList = getOlccStudentsList();

    try {

        Map<OlccStudent, String> map = getInvalidStudentsMap(olccStudentsList);
        System.out.println();
        //olccStudentService.getStudentsMap(olccStudentsList);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private List<OlccStudent> getOlccStudentsList() {

    List<OlccStudent> olccStudentsList = new ArrayList<>();

    OlccStudent student1 = new OlccStudent(1L, 1L, "firstName1", "middleInitial1", "lastName1", "email1", 
            "streetAdress1", "city1", "state1", "1234", "01/22/2015", "phoneNumber1", "01/22/2015", 
            "123456789", "testForm1", "providerCode1", "instructorCode1", "surveyAnswer1", 
            "testIdentifier1",  "testAnswers1");

    OlccStudent student2 = new OlccStudent(2L, 2L, "firstName2", "middleInitial2", "lastName2", "email2", 
            "streetAdress2", "city2", "state2", "5678", "02/22/2015", "phoneNumber2", "02/22/2015", 
            "987654321", "testForm2", "providerCode2", "instructorCode2", "surveyAnswer2", 
            "testIdentifier2",  "testAnswers2");

    OlccStudent student3 = new OlccStudent(3L,3L, "firstName3", "middleInitial3", "lastName3", "email3", 
            "streetAdress3", "city3", "state3", "zip3", "testDate3", "phoneNumber3", "dateOfBirth3", 
            "socialSecurityNumber3", "testForm3", "providerCode3", "instructorCode3", "surveyAnswer3", 
            "testIdentifier3",  "testAnswers3");

    OlccStudent student4 = new OlccStudent(4L, 4L, "firstName4", "middleInitial4", "lastName4", "email4", 
            "streetAdress4", "city4", "state4", "zip4", "testDate4", "phoneNumber4", "dateOfBirth4", 
            "socialSecurityNumber4", "testForm4", "providerCode4", "instructorCode4", "surveyAnswer4", 
            "testIdentifier4",  "testAnswers4");

    olccStudentsList.add(student1);
    olccStudentsList.add(student2);
    olccStudentsList.add(student3);
    olccStudentsList.add(student4);

    return olccStudentsList;
}

private String validate(OlccStudent student) {

    String firstName = student.getFirstName();
    String middleInitial = student.getMiddleInitial();
    String lastName = student.getLastName();
    String streetAddress = student.getStreetAddress();
    String city = student.getCity();
    String state = student.getState();
    String zip = student.getZip();
    String dateOfBirth = student.getDateOfBirth();
    String ssn = student.getSocialSecurityNumber();
    String phoneNumber = student.getPhoneNumber();
    String testDate = student.getTestDate();
    String testForm = student.getTestForm();
    String testAnswers = student.getTestAnswers();
    String providerCode = student.getProviderCode();
    String instructorCode = student.getInstructorCode();

    StringBuilder errorBuilder = new StringBuilder();

    //The predicate 'negate' method returns a predicate that represents the logical negation or opposite
    if (isValidFirstName().negate().test(student)) {
        String error = "Invalid FirstName: " + firstName;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidMiddleInitial().negate().test(student)) {
        String error = "Invalid Middle Initial: " + middleInitial;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidLastName().negate().test(student)) {
        String error = "Invalid LastName: " + lastName;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidStreetAddress().negate().test(student)) {
        String error = "Invalid StreetAddress: " + streetAddress;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidCity().negate().test(student)) {
        String error = "Invalid City: " + city;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidState().negate().test(student)) {
        String error = "Invalid State: " + state;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidZip().negate().test(student)) {
        String error = "Invalid Zip: " + zip;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidDateOfBirth().negate().test(student)) {
        String error = "Invalid DateOfBirth: " + dateOfBirth;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidSsn().negate().test(student)) {
        String error = "Invalid SSN: " + ssn;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidTestDate().negate().test(student)) {
        String error = "Invalid TestDate: " + testDate;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidTestAnswers().negate().test(student)) {
        String error = "Invalid TestAnswers: " + testAnswers;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidProviderCode().negate().test(student)) {
        String error = "Invalid ProvideCode: " + providerCode;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (isValidInstructorCode().negate().test(student)) {
        String error = "Invalid InstructorCode: " + instructorCode;
        errorBuilder.append(error + ERROR_MESSAGE_SEPERATOR);
    }

    if (errorBuilder.length() > 0) {
        errorBuilder.deleteCharAt(errorBuilder.length() - 1);
    } 

    return errorBuilder.toString().trim();
}

public Map<OlccStudent, String> getInvalidStudentsMap(List<OlccStudent> studentsList) throws Exception {

    Map<OlccStudent, String> map = studentsList.stream()
      // Step 1: Validate each student, keeping a track of any error message generated.
      .collect(Collectors.toMap(Function.identity(), student -> validate(student)))
      // Step 2: Keep only those that have an error message associated.
      .entrySet()
      .stream()
      .filter(entry -> entry.getValue() != null)
      // Step 3: Generate a Map.
      .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue()));

    return map;

}

2 个答案:

答案 0 :(得分:2)

我会创建一个<div> yolo </div> <script type="text/javascript"> var temp = 'jojo'; $.ajax({ url: 'test2.php', //Loco success: function(data) { temp = data; $('div').html(data); }, error: function (err) { alert('error'); } }); alert(temp); var toBeUsedLater = temp; //updated temp value from ajax call refreshTab(); </script> 类来将验证谓词和错误消息格式化程序粘在一起:

ValidationRule

现在static class ValidationRule { public final Predicate<OlccStudent> predicate; public final Function<OlccStudent, String> errorFormatter; public ValidationRule(Predicate<OlccStudent> predicate, Function<OlccStudent, String> errorFormatter) { this.predicate = predicate; this.errorFormatter = errorFormatter; } } 将如下所示:

getAllRules

您可以通过以下方式获取无效学生的地图:

public static List<ValidationRule> getAllRules() {
    return Arrays.asList(
        new ValidationRule(isValidFirstName(), s -> "Invalid FirstName: " + s.getFirstName()),
        new ValidationRule(isValidMiddleInitial(), s -> "Invalid Middle Initial: " + s.getMiddleInitial()),
        new ValidationRule(isValidLastName(), s -> "Invalid LastName: " + s.getLastName()),
        new ValidationRule(isValidStreetAddress(), s -> "Invalid StreetAddress: " + s.getStreetAddress())
        // ...
        );
}

答案 1 :(得分:0)

第1部分:从Map个对象生成Collection

如果我正确理解了您的问题,您希望从Map个对象生成Collection,以便Map中的值是在验证{中的对象时生成的错误消息{1}}并且密钥是验证失败的实际对象。

因此,如果您的输入Collection是:

Collection

预期输出为:

Student 1: Valid
Student 2: Valid
Student 3: Invalid
Student 4: Valid
Student 5: Invalid

如果这是你想要的,你的问题过于复杂,可以通过假设存在如下函数来简化:

Student 3: {error message}
Student 5: {error message}

现在,任务很简单。

/**
 * Validates a student and returns an error message if the student data is
 * not valid.  The error message provides the actual reason why the student
 * data is invalid.
 *
 * @param student The student to validate.
 * @return An error message if {@code student} contains invalid data,
 *         {@code null} otherwise.
 */
String validate(OlccStudent student) { ... }

第2部分:验证对象

最好使用JSR303-Java Validation API(以及其中一个实现,如Hibernate Validator或Apache Beans Validator)来验证bean。这不仅标准化,而且需要更少的努力和更少的维护。添加新验证很简单,整个框架与区域设置无关,允许生成特定于语言环境的消息。