首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将员工调查数据从CSV转换为JSON

将员工调查数据从CSV转换为JSON
EN

Code Review用户
提问于 2018-10-18 12:15:31
回答 1查看 1.1K关注 0票数 1

这个Java代码项目是为了获得工作机会而提交的,但由于显示了“可能很难取消学习的坏习惯”而被标记出来,但我对这意味着什么感到困惑。请给我任何接受者。如何以不同的方式处理或改进。

我已经删除了对有关公司的任何提及,但这一挑战是这样提出的:

问题描述

已经进行了一项员工调查,并要求你从中找出有用的见解。您将数据作为单位CSV文件提供给整个公司的所有员工,其中至少包含以下列: divisionId、teamId、managerId、employeeId、firstName、lastName,生日--例如,CSV文件的一条记录(行)如下: 1,7,3,24,乔恩,雪诺,1986-12-26基于上述结构的目标,编写一段以CSV为输入的代码,并创建一个JSON对象,该对象如下所示:{“divisionId”:{ "#divisionId":{ "teams":{“工作组”:{ "managers":{ "#managerId":{ "employees":{“#雇员”:{ "id":"#employeeId","firstName":“乔恩”,"lastName":“雪”,“生日”:"1986-12-26“}注意:您可以在data.csv目录中找到数据集为/data。问题

  1. 您刚刚编写的算法的大O运行时复杂度是多少?
  2. 您能编写代码使所有ID在JSON输出中按升序排列吗?
  3. 您能否创建这样的列表,使员工列表按其全名进行排序?(如果您为任意排序顺序(例如,变量/多个排序字段、升序和/或降序)创建了一种机制,则加分)
  4. 你能计算出公司、部门、团队和经理的平均年龄吗?

注意:对于每个额外的问题,您可以创建不同的命令行参数来更改应用程序的模式。然而,这只是一个建议,您是否可以自由地采取任何您希望的替代方法。除非另有明确要求,否则我们期望使用以下内容:

  • Java 8
  • 分级作为构建系统
  • 任何必要的库(例如,Jackson用于JSON)

代码:

CSVData.Java

代码语言:javascript
复制
package org.challenge.csv;

import java.util.Arrays;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnore;

/*
 * Base class for CSV data
 *   
 */
public class CSVData {

    private transient final String[] fieldsInCSVHeader;

    protected CSVData(String[] fieldsInCSVHeader) {
        this.fieldsInCSVHeader = fieldsInCSVHeader;
    }

    @JsonIgnore
    public List getHeaderFields() {
        return Arrays.asList(fieldsInCSVHeader);
    }

    public enum SortDirection {
        ASCENDING,
        DESCENDING
    }
}

CSVParser.java

代码语言:javascript
复制
package org.challenge.csv;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Objects;

import static java.util.stream.Collectors.*;

import org.challenge.csv.survey.SurveyCSVParser;
import org.challenge.csv.survey.SurveyCSVParser.SurveyCSVData;

/**
 * Base class for CSV parsers
 *
 */
public class CSVParser {

    private final File csvFile;
    private final short minimumFieldsPerLine;
    private final String seperatorOfFields;

    private List linesOfCSVFile;

    protected CSVParser(File csvFile, short minimumFieldsPerLine, String seperatorOfFields) {
        this.csvFile = csvFile;
        this.minimumFieldsPerLine = minimumFieldsPerLine;
        this.seperatorOfFields = seperatorOfFields;
    }

    public static Parser createSurveyParser(File csvFile, SurveyCSVData.Employee.SortOrder order, CSVData.SortDirection direction) {
        Objects.requireNonNull(csvFile);
        return new SurveyCSVParser(csvFile, order, direction);
    }
    public static Parser createSurveyParser(File csvFile) {
        return new SurveyCSVParser(csvFile, SurveyCSVData.Employee.SortOrder.ORIGINAL, CSVData.SortDirection.ASCENDING);
    }

    protected boolean fileExists() {
        return csvFile.exists() && csvFile.canRead();
    }
    protected boolean fileIsCorrectlyFormatted() {
        readFile();     
        return linesOfCSVFile.size() > 0 && linesOfCSVFile.get(0).split(seperatorOfFields).length >= minimumFieldsPerLine;
    }
    protected List fileLines() {
        readFile();
        return linesOfCSVFile.stream().skip(1).collect(toList());
    }

    private synchronized void readFile()
    {
        try {
            if (null == linesOfCSVFile) {
                if (true == fileExists())
                    linesOfCSVFile = Files.readAllLines(csvFile.toPath());      // NOTE - BufferedReader may be preferred for very large files, can then process line by line or in chunks...
            }
        }
        catch (IOException e) {
            // NOTE - Retry in a limited loop, ...
            throw new RuntimeException("FAILED to read file content");
        }
    }
}

Parser.java

代码语言:javascript
复制
package org.challenge.csv;

import java.util.Optional;

/*
 * Interface defining CSV parser functions
 * 
 */
public interface Parser {
    /**
     * Parse CSV file into an object structure
     * @return CSV data object
     */
    Optional parse();
}

JSONWriter.java

代码语言:javascript
复制
package org.challenge.json;

import org.challenge.csv.CSVData;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;


/**
 * Class for writing JSON data from object graph via Jackson libraries
 *
 */
public final class JSONWriter {

    private final CSVData csvData;

    public JSONWriter(CSVData csvData) {
        this.csvData = csvData;
    }

    public String write() throws JsonProcessingException {

        ObjectMapper objectToJsonMapper = new ObjectMapper();
        String jsonStringRepresentation = objectToJsonMapper.writeValueAsString(csvData);       
        return jsonStringRepresentation;
    }
}

SurveyCSVParser.java

代码语言:javascript
复制
package org.challenge.csv.survey;

import java.io.File;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.StringTokenizer;
import java.util.TreeMap;

import org.challenge.csv.CSVData;
import org.challenge.csv.CSVParser;
import org.challenge.csv.Parser;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
 * Class for parsing CSV data related to employee survey
 *
 */
public final class SurveyCSVParser extends CSVParser implements Parser {

    private static final short MIN_TOKENS_PER_LINE = 7;
    private static final String SEPERATOR_OF_TOKENS = ",";

    private final SurveyCSVData.Employee.SortOrder sortOrderOfDataOrEmployees;
    private final CSVData.SortDirection sortDirectionOfEmployees;

    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-M-d");

    public SurveyCSVParser(File csvFile, SurveyCSVData.Employee.SortOrder sortOrderOfDataOrEmployees, CSVData.SortDirection sortDirectionOfEmployees) {
        super(csvFile, MIN_TOKENS_PER_LINE, SEPERATOR_OF_TOKENS);
        this.sortOrderOfDataOrEmployees = sortOrderOfDataOrEmployees;
        this.sortDirectionOfEmployees = sortDirectionOfEmployees;
    }

    @Override
    public Optional parse() {
        SurveyCSVData csvDataParsed = null;

        if (fileExists() && fileIsCorrectlyFormatted()) {
            List linesOfCSV = fileLines();
            SurveyCSVData csvData = new SurveyCSVData(sortOrderOfDataOrEmployees);
            try {
                if (SurveyCSVData.Employee.SortOrder.ORIGINAL != sortOrderOfDataOrEmployees)
                    linesOfCSV.parallelStream().forEach(l -> processLineOfCSV(l, csvData, sortOrderOfDataOrEmployees, sortDirectionOfEmployees));       
                else
                    linesOfCSV.stream().forEach(l -> processLineOfCSV(l, csvData, sortOrderOfDataOrEmployees, sortDirectionOfEmployees));   
                csvDataParsed = csvData;
            }
            catch (Exception e) {                       
                throw new RuntimeException("FAILED to parse CSV file");     // NOTE - Should a "bad" line prevent the remainder of the parse?
            }
        }

        return Optional.ofNullable(csvDataParsed);
    }

    private static void processLineOfCSV(String line, SurveyCSVData data, SurveyCSVData.Employee.SortOrder sortOrderOfDataOrEmployees, CSVData.SortDirection sortDirectionOfEmployees)
    {
        StringTokenizer tokenizer = new StringTokenizer(line, SEPERATOR_OF_TOKENS);
        short indexOfTokenFound = 0;
        String divisionId = null, teamId = null, managerId = null, employeeId = null, lastName = null, firstName = null, birthdate = null;      
        while (tokenizer.hasMoreTokens() && indexOfTokenFound < MIN_TOKENS_PER_LINE) {

            String token = tokenizer.nextToken();
            switch (indexOfTokenFound) {
                case 0:
                    divisionId = token;
                    break;
                case 1:
                    teamId = token;
                    break;
                case 2:
                    managerId = token;
                    break;
                case 3:
                    employeeId = token;
                    break;
                case 4:
                    firstName = token;
                    break;
                case 5:
                    lastName = token;
                    break;
                case MIN_TOKENS_PER_LINE-1:
                    birthdate = token;
                    break;
                default:
                    assert false;
            }
            indexOfTokenFound++;
        }

        if (indexOfTokenFound >= MIN_TOKENS_PER_LINE)
            buildSurveyData(divisionId, teamId, managerId, employeeId, firstName, lastName, birthdate, data, sortOrderOfDataOrEmployees, sortDirectionOfEmployees);
    }

    private static synchronized void buildSurveyData(String divisionId, String teamId, String managerId, String employeeId, String firstName, String lastName, String birthdate, SurveyCSVData data, SurveyCSVData.Employee.SortOrder sortOrderOfDataOrEmployees, CSVData.SortDirection direction) 
    {
        Objects.requireNonNull(divisionId);
        Objects.requireNonNull(teamId);
        Objects.requireNonNull(managerId);
        Objects.requireNonNull(employeeId);
        Objects.requireNonNull(firstName);
        Objects.requireNonNull(lastName);
        Objects.requireNonNull(birthdate);

        Integer divisionIdBox = Integer.parseInt(divisionId);
        Integer teamIdBox = Integer.parseInt(teamId);
        Integer managerIdBox = Integer.parseInt(managerId);
        Integer employeeIdBox = Integer.parseInt(employeeId);

        if (false == data.divisions.containsKey(divisionIdBox))
             data.divisions.put(divisionIdBox, new SurveyCSVData.Division(divisionIdBox, sortOrderOfDataOrEmployees));
        SurveyCSVData.Division division = data.divisions.get(divisionIdBox);

        if (false == division.teams.containsKey(teamIdBox))
            division.teams.put(teamIdBox, division.createTeam(teamIdBox));
        SurveyCSVData.Team team = division.teams.get(teamIdBox);

        if (false == team.managers.containsKey(managerIdBox))
            team.managers.put(managerIdBox, team.createManager(managerIdBox, direction));
        SurveyCSVData.Manager manager = team.managers.get(managerIdBox);

        if (false == manager.employees.containsKey(employeeIdBox)) 
            manager.employees.put(employeeIdBox, manager.createEmployee(employeeIdBox, firstName, lastName, birthdate));        // NOTE - Duplicates will not be added more than once
    }

    /**
     * 
     * Class representing survey data
     *
     */
    public final static class SurveyCSVData extends CSVData {

        private static final short VERSION = 1;                 // NOTE - Good idea to apply version to data structures

        private Map divisions;

        public SurveyCSVData(Employee.SortOrder sortOrderOfDataOrEmployees) {
            super(new String[] {"divisionId", "teamId", "managerId", "employeeId", "lastName", "firstName", "birthdate"});
            if (Employee.SortOrder.ORIGINAL == sortOrderOfDataOrEmployees)
                divisions = new LinkedHashMap <>();
            else
                divisions = new TreeMap<>();
        }

        public void addDivision(Integer id, Division division) {
            Objects.requireNonNull(id); Objects.requireNonNull(division);
            divisions.put(id, division);
        }

        public Map  getDivisions() {
            return Collections.unmodifiableMap(divisions);  
        }

        /**
         * Class representing division in survey data
         */
        public final static class Division {

            private Map teams;

            private transient final Integer id;
            private final Employee.SortOrder sortOrderOfDataOrEmployees;

            public Division(Integer id, Employee.SortOrder sortOrderOfDataOrEmployees) {
                this.id = id;
                this.sortOrderOfDataOrEmployees = sortOrderOfDataOrEmployees;
                if (Employee.SortOrder.ORIGINAL == sortOrderOfDataOrEmployees)
                    teams = new LinkedHashMap <>();
                else
                    teams = new TreeMap<>();
            }

            @JsonIgnore
            public Integer getId() {
                return id; 
            }   

            public void addTeam(Integer id, Team team) {
                Objects.requireNonNull(id); Objects.requireNonNull(team);
                teams.put(id, team);
            }
            public Team createTeam(Integer id) {
                return new Team(id, sortOrderOfDataOrEmployees);
            }

            public Map getTeams() {
                return Collections.unmodifiableMap(teams);  
            }       
        }

        /**
         * Class representing team in survey data
         */
        public final static class Team {

            private Map managers;

            private transient final Integer id;
            private final Employee.SortOrder sortOrderOfDataOrEmployees;

            public Team(Integer id, Employee.SortOrder sortOrderOfDataOrEmployees) {
                this.id = id;
                this.sortOrderOfDataOrEmployees = sortOrderOfDataOrEmployees;
                if (Employee.SortOrder.ORIGINAL == sortOrderOfDataOrEmployees)
                    managers = new LinkedHashMap <>();
                else
                    managers = new TreeMap<>();
            }

            @JsonIgnore
            public Integer getId() {
                return id; 
            }

            public void addManager(Integer id, Manager manager) {
                Objects.requireNonNull(id); Objects.requireNonNull(manager);
                managers.put(id, manager);
            }           
            public Manager createManager(Integer id, CSVData.SortDirection sortDirectionOfEmployees) {
                return new Manager(id, sortOrderOfDataOrEmployees, sortDirectionOfEmployees);
            }

            public Map getManagers() {
                return Collections.unmodifiableMap(managers);   
            }           
        }

        /**
         * Class representing manager in survey data
         */
        public final static class Manager {

            private final Employee.SortOrder sortOrderOfDataOrEmployees;
            private final CSVData.SortDirection sortDirectionOfEmployees;

            private transient Map employees;

            private transient final Integer id;

            public Manager(Integer id, Employee.SortOrder sortOrderOfDataOrEmployees, CSVData.SortDirection sortDirectionOfEmployees) {
                this.id = id;
                this.sortOrderOfDataOrEmployees = sortOrderOfDataOrEmployees;
                this.sortDirectionOfEmployees = sortDirectionOfEmployees;
                if (Employee.SortOrder.ORIGINAL == sortOrderOfDataOrEmployees)
                    employees = new LinkedHashMap <>();
                else
                    employees = new TreeMap<>();
            }

            @JsonIgnore
            public Integer getId() {
                return id; 
            }   

            public void addEmployee(Integer id, Employee employee) {
                Objects.requireNonNull(id); Objects.requireNonNull(employee);
                employees.put(id, employee);
            }
            public Employee createEmployee(Integer id, String firstName, String lastName, String birthdate) {
                return new Employee(id, firstName, lastName, birthdate);
            }

            public Map getEmployees() {
                return Collections.unmodifiableMap(employees);  
            }

            @JsonProperty("employees")
            public Map getOrderedEmployees() {

                Map orderedMapOfEmployees;
                if ((Employee.SortOrder.ID == sortOrderOfDataOrEmployees && CSVData.SortDirection.ASCENDING == sortDirectionOfEmployees) || Employee.SortOrder.ORIGINAL == sortOrderOfDataOrEmployees)
                    orderedMapOfEmployees = employees;
                else {
                    Comparator valueComparator = (k1, k2) -> {
                          Employee e1 = employees.get(k1);
                          Employee e2 = employees.get(k2);
                          int compare = 0;
                          if(null != e1 && null != e2) {
                              switch (sortOrderOfDataOrEmployees) {
                                case ID:
                                    compare = Integer.valueOf(e1.id).compareTo(Integer.valueOf(e2.id)); 
                                    break;      
                                case LASTNAME:
                                    compare = e1.lastName.compareTo(e2.lastName);       
                                    break;                          
                                case FIRSTNAME:
                                    compare = e1.firstName.compareTo(e2.firstName);     
                                    break;  
                                case BIRTHDATE:
                                    compare = e1.birthdate.compareTo(e2.birthdate);     
                                    break;
                                default:
                                    assert false;
                                    break;
                              }
                              if (CSVData.SortDirection.DESCENDING == sortDirectionOfEmployees)
                                  compare = -compare;
                          }
                          else
                              throw new NullPointerException("Comparator does not support null values");
                          return compare;
                    };

                    Map sortedMapOfEmployees = new TreeMap<>(valueComparator);
                    sortedMapOfEmployees.putAll(employees);
                    orderedMapOfEmployees = sortedMapOfEmployees;
                }
                return orderedMapOfEmployees;
            }

            @Override                   
            public String toString() {
                return Objects.toString(employees); 
            }
        }

        /**
         * Class representing employee in survey data
         */
        public final static class Employee {

            private final int id;
            private final String firstName;
            private final String lastName;          
            private final String birthdate;

            private transient final LocalDate birthdateDateType;

            public Employee(int id, String firstName, String lastName, String birthdate) {
                this.id = id;
                this.firstName = firstName;
                this.lastName = lastName;
                this.birthdate = birthdate;
                this.birthdateDateType = LocalDate.parse(birthdate, FORMATTER);         // NOTE - Formatter is not thread safe
            }

            public int getId() {
                return id;
            }
            public String getFirstName() {
                return firstName;
            }
            public String getLastName() {
                return lastName;
            }
            public String getBirthdate() {
                return birthdate;
            }
            @JsonIgnore
            public LocalDate getBirthdateDateType() {
                return birthdateDateType;
            }

            @Override                   
            public String toString() {
                return "(id='" + id + "', firstName='" + firstName + "', lastName='" + lastName + "', birthdate='" + birthdate + "')";
            }

            public enum SortOrder {
                ORIGINAL,
                ID,
                LASTNAME,
                FIRSTNAME,
                BIRTHDATE
            }
        }       
    }
}

AgeCalculator.java

代码语言:javascript
复制
package org.challenge.analysis;

import java.time.Period;
import java.util.Optional;

/**
 * Interface for obtaining average age from survey data at different scopes
 *
 */
public interface AgeCalculator {

    /**
     * Calculate average age of employees within a specified scope
     * @param scope enum value
     * @param id of division, team or manager, can be not present for company scope
     * @return Period of time showing the average age
     * @exception  AgeCalculatorException if id is not present for non-company scope
     */
    Period getAverageAge(Scope scope, Optional id) throws AgeCalculatorException;

    public enum Scope {
        COMPANY,
        DIVISION,           
        TEAM,
        MANAGER
    }

    /**
     * Exception class for age calculator
     */
    class AgeCalculatorException extends Exception {
        private static final long serialVersionUID = 1L;

        AgeCalculatorException(String message) {
            super(message);
        }
        AgeCalculatorException(String message, Exception inner) {
            super(message, inner);
        }
    }   
}

SurveyAnalyzer.java

代码语言:javascript
复制
package org.challenge.analysis;

import java.time.Duration;
import java.time.LocalDate;
import java.time.Period;
import java.util.Objects;
import java.util.Optional;

import org.challenge.csv.survey.SurveyCSVParser;

/**
 * Class implementing average age calculations on survey data  
 *
 */
public final class SurveyAnalyzer implements AgeCalculator {

    private final SurveyCSVParser.SurveyCSVData surveyData;

    public SurveyAnalyzer(SurveyCSVParser.SurveyCSVData surveyData) {
        this.surveyData = surveyData;
    }

    @Override
    public Period getAverageAge(Scope scope, Optional id) throws AgeCalculator.AgeCalculatorException {

        if (AgeCalculator.Scope.COMPANY != scope && (null == id || false == id.isPresent()))
            throw new AgeCalculator.AgeCalculatorException("For non-COMPANY scope an identifier is required");

        long totalDaysAgeOfEmployeesInScope, totalEmployeesInScope;     
        switch (scope) {

            default:    
            //case COMPANY:
                totalDaysAgeOfEmployeesInScope = surveyData.getDivisions().values().parallelStream()
                        .flatMap(d -> d.getTeams().values().parallelStream())
                        .flatMap(t -> t.getManagers().values().parallelStream())
                        .flatMap(m -> m.getEmployees().values().parallelStream())
                        .mapToLong(e -> Duration.between(e.getBirthdateDateType().atStartOfDay(), LocalDate.now().atStartOfDay()).toDays()).sum();
                totalEmployeesInScope = surveyData.getDivisions().values().parallelStream()
                        .flatMap(d -> d.getTeams().values().parallelStream())
                        .flatMap(t -> t.getManagers().values().parallelStream())
                        .flatMap(m -> m.getEmployees().values().parallelStream())
                        .count();
                break;
            case DIVISION:
                totalDaysAgeOfEmployeesInScope = surveyData.getDivisions().values().parallelStream()
                        .filter(d -> Objects.equals(d.getId(), id.get()))
                        .flatMap(d -> d.getTeams().values().parallelStream())
                        .flatMap(t -> t.getManagers().values().parallelStream())
                        .flatMap(m -> m.getEmployees().values().parallelStream())
                        .mapToLong(e -> Duration.between(e.getBirthdateDateType().atStartOfDay(), LocalDate.now().atStartOfDay()).toDays()).sum();
                totalEmployeesInScope = surveyData.getDivisions().values().parallelStream()
                        .filter(d -> Objects.equals(d.getId(), id.get()))
                        .flatMap(d -> d.getTeams().values().parallelStream())
                        .flatMap(t -> t.getManagers().values().parallelStream())
                        .flatMap(m -> m.getEmployees().values().parallelStream())
                        .count();
                break;
            case TEAM:
                totalDaysAgeOfEmployeesInScope = surveyData.getDivisions().values().parallelStream()
                        .flatMap(d -> d.getTeams().values().parallelStream())
                        .filter(t -> Objects.equals(t.getId(), id.get()))
                        .flatMap(t -> t.getManagers().values().parallelStream())
                        .flatMap(m -> m.getEmployees().values().parallelStream())
                        .mapToLong(e -> Duration.between(e.getBirthdateDateType().atStartOfDay(), LocalDate.now().atStartOfDay()).toDays()).sum();
                totalEmployeesInScope = surveyData.getDivisions().values().parallelStream()
                        .flatMap(d -> d.getTeams().values().parallelStream())
                        .filter(t -> Objects.equals(t.getId(), id.get()))
                        .flatMap(t -> t.getManagers().values().parallelStream())
                        .flatMap(m -> m.getEmployees().values().parallelStream())
                        .count();
                break;
            case MANAGER:
                totalDaysAgeOfEmployeesInScope = surveyData.getDivisions().values().parallelStream()
                        .flatMap(d -> d.getTeams().values().parallelStream())
                        .flatMap(t -> t.getManagers().values().parallelStream())
                        .filter(m -> Objects.equals(m.getId(), id.get()))
                        .flatMap(m -> m.getEmployees().values().parallelStream())
                        .mapToLong(e -> Duration.between(e.getBirthdateDateType().atStartOfDay(), LocalDate.now().atStartOfDay()).toDays()).sum();
                totalEmployeesInScope = surveyData.getDivisions().values().parallelStream()
                        .flatMap(d -> d.getTeams().values().parallelStream())
                        .flatMap(t -> t.getManagers().values().parallelStream())
                        .filter(m -> Objects.equals(m.getId(), id.get()))
                        .flatMap(m -> m.getEmployees().values().parallelStream())
                        .count();
                break;
        }

        long averageAgeDays = 0;
        if (totalEmployeesInScope > 0)
            averageAgeDays = (long)Math.floor(totalDaysAgeOfEmployeesInScope / totalEmployeesInScope);      // NOTE - Some rounding down here to nearest day over all employees in scope
        Period averageAge = Period.between(LocalDate.now(), LocalDate.now().plusDays(averageAgeDays));
        return averageAge;
    }
}

Task1.java

代码语言:javascript
复制
package org.challenge;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Period;
import java.util.Objects;
import java.util.Optional;

import org.challenge.analysis.AgeCalculator;
import org.challenge.analysis.AgeCalculator.AgeCalculatorException;
import org.challenge.analysis.SurveyAnalyzer;
import org.challenge.csv.CSVData;
import org.challenge.csv.CSVParser;
import org.challenge.csv.Parser;
import org.challenge.csv.survey.SurveyCSVParser;
import org.challenge.json.JSONWriter;


/**
 * Main class with entry point
 *
 */
class Task1 {

    /**
     * Main entry point
     * @param args
     */
    public static void main(String[] args) {

        try {
            // Path to supplied CSV data file
            Path csvFilePath = Paths.get("data", "data.csv");

            // Process command-line arguments for sort order and direction
            org.challenge.csv.survey.SurveyCSVParser.SurveyCSVData.Employee.SortOrder employeeSortOrder = processSortOrder(args);
            org.challenge.csv.CSVData.SortDirection employeeSortDirection = processSortAscendingDescending(args);

            // Create the parser
            Parser csvParser = CSVParser.createSurveyParser(csvFilePath.toFile(), employeeSortOrder, employeeSortDirection);

            long timeBeforeWorkMs = System.nanoTime();

            // Parse into object structure
            Optional csvDataObjectsOrNull = csvParser.parse();     
            if (true == csvDataObjectsOrNull.isPresent())
            {
                CSVData csvDataObjects = csvDataObjectsOrNull.get();
                Objects.requireNonNull(csvDataObjects, "FAILED to parse CSV");

                // Create the writer
                JSONWriter writerofJson = new JSONWriter(csvDataObjects);

                // Write out objects as JSON
                String jsonStringRepresentation = writerofJson.write();
                Objects.requireNonNull(jsonStringRepresentation, "FAILED to output JSON");

                System.out.println("Processed in " + (System.nanoTime() - timeBeforeWorkMs) + "ms");

                // Dump JSON to console
                System.out.println("JSON formatted survey data");
                System.out.println(jsonStringRepresentation);                           // NOTE - Verify and pretty print JSON output at https://jsonlint.com/

                // Check we have survey data
                if (true == csvDataObjects instanceof SurveyCSVParser.SurveyCSVData) {

                    SurveyCSVParser.SurveyCSVData surveyData = (SurveyCSVParser.SurveyCSVData)csvDataObjects;

                    // Dump some sample object data to console
                    SurveyCSVParser.SurveyCSVData.Manager sampleManager = surveyData.getDivisions().get(1).getTeams().get(5).getManagers().get(1);
                    System.out.println("Division 1, Team 5, Manager 1 has employees: " + sampleManager);

                    try {
                        // Create survey data analyzer
                        AgeCalculator averageAgeCalculator = new SurveyAnalyzer(surveyData);
                        Period averageAge;

                        // Calculate some sample average ages and dump to console
                        averageAge = averageAgeCalculator.getAverageAge(AgeCalculator.Scope.COMPANY, Optional.empty());
                        System.out.println("Average age of employees in company: " + formatPeriod(averageAge));

                        averageAge = averageAgeCalculator.getAverageAge(AgeCalculator.Scope.DIVISION, Optional.of(1));      // NOTE - Samples only, not added to command line arguments
                        System.out.println("Average age of employees in division 1: " + formatPeriod(averageAge));

                        averageAge = averageAgeCalculator.getAverageAge(AgeCalculator.Scope.TEAM, Optional.of(12));
                        System.out.println("Average age of employees in team 12: " + formatPeriod(averageAge));

                        averageAge = averageAgeCalculator.getAverageAge(AgeCalculator.Scope.MANAGER, Optional.of(2));
                        System.out.println("Average age of employees under manager 2: " + formatPeriod(averageAge));
                    }
                    catch (AgeCalculatorException e) {
                        System.out.println("AGE EXCEPTION: " + e.toString());
                    }
                }
                else {
                    System.out.println("UNEXPECTED CSV data type");
                }
            }
            else {
                System.out.println("FAILED to parse CSV data");
            }

            System.out.flush();
        }
        catch (Exception e) {
            System.out.println("EXCEPTION: " + e.toString());
        }
    }

    private static org.challenge.csv.survey.SurveyCSVParser.SurveyCSVData.Employee.SortOrder processSortOrder(String[] args) {

        org.challenge.csv.survey.SurveyCSVParser.SurveyCSVData.Employee.SortOrder sortOrder = org.challenge.csv.survey.SurveyCSVParser.SurveyCSVData.Employee.SortOrder.ORIGINAL;

        if (args.length > 0) {
            try {
                sortOrder = Enum.valueOf(org.challenge.csv.survey.SurveyCSVParser.SurveyCSVData.Employee.SortOrder.class, args[0]);             
            }
            catch (IllegalArgumentException e) {
                System.out.println("FAILED to process sort order, defaulting to ORIGINAL");
            }
        }
        System.out.println("Sort order is " + sortOrder.name());

        return sortOrder;
    }

    private static org.challenge.csv.CSVData.SortDirection processSortAscendingDescending(String[] args) {

        org.challenge.csv.CSVData.SortDirection sortDirection = org.challenge.csv.CSVData.SortDirection.ASCENDING;

        if (args.length > 1) {
            if (true == "DESC".equalsIgnoreCase(args[1]))
                sortDirection = org.challenge.csv.CSVData.SortDirection.DESCENDING;         
        }
        System.out.println("Sort direction is " + sortDirection.name());

        return sortDirection;       
    }

    private static String formatPeriod(Period period) {
        String formattedPeriod = String.format("%d years, %d months, %d days", period.getYears(), period.getMonths(), period.getDays());
        return formattedPeriod;
    }
}

测试:

CSVParserTests.java

代码语言:javascript
复制
package org.challenge.csv;

import static org.junit.Assert.*;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;

import org.challenge.csv.survey.SurveyCSVParser.SurveyCSVData;

import org.junit.Test;

public class CSVParserTests {

    @Test
    public void testParse_givenCSV_success() {

        Path csvFilePath = Paths.get("data", "data.csv");

        Parser csvParser = CSVParser.createSurveyParser(csvFilePath.toFile());
        assertNotNull(csvParser);

        Optional csvData = csvParser.parse();  
        assertNotNull(csvData.orElse(null));
        assertTrue(csvData.get() instanceof SurveyCSVData);
        SurveyCSVData surveyData = (SurveyCSVData)csvData.get();
        assertNotNull(surveyData.getDivisions());
        assertNotNull(surveyData.getDivisions().get(1));
    }

    @Test
    public void testParse_emptyCSV_success() {

        Path csvFilePath = Paths.get("data", "empty.csv");

        Parser csvParser = CSVParser.createSurveyParser(csvFilePath.toFile());
        assertNotNull(csvParser);

        Optional csvData = csvParser.parse();  
        assertNotNull(csvData.orElse(null));
        assertTrue(csvData.get() instanceof SurveyCSVData);
        SurveyCSVData surveyData = (SurveyCSVData)csvData.get();
        assertNotNull(surveyData.getDivisions());
        assertEquals(0, surveyData.getDivisions().size());
    }

    @Test
    public void testParse_extraCSV_success() {

        Path csvFilePath = Paths.get("data", "extra.csv");

        Parser csvParser = CSVParser.createSurveyParser(csvFilePath.toFile());
        assertNotNull(csvParser);

        Optional csvData = csvParser.parse();  
        assertNotNull(csvData.orElse(null));
        assertTrue(csvData.get() instanceof SurveyCSVData);
        SurveyCSVData surveyData = (SurveyCSVData)csvData.get();
        assertNotNull(surveyData.getDivisions());
        assertNotNull(surveyData.getDivisions().get(1));
    }

    @Test
    public void testParse_badCSV_failure() {

        Path csvFilePath = Paths.get("data", "badformat.csv");

        Parser csvParser = CSVParser.createSurveyParser(csvFilePath.toFile());
        assertNotNull(csvParser);

        Optional csvData = csvParser.parse();  
        assertNull(csvData.orElse(null));
    }

    @Test
    public void testParse_nonExistantCSV_failure() {

        Path csvFilePath = Paths.get("data", "missing.csv");

        Parser csvParser = CSVParser.createSurveyParser(csvFilePath.toFile());
        assertNotNull(csvParser);

        Optional csvData = csvParser.parse();  
        assertNull(csvData.orElse(null));
    }
}

JSONWriterTests.java

代码语言:javascript
复制
package org.challenge.json;

import static org.junit.Assert.*;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

import org.challenge.csv.CSVData;
import org.challenge.csv.survey.SurveyCSVParser;

import org.junit.Test;

import com.fasterxml.jackson.core.JsonProcessingException;

public class JSONWriterTests {

    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-M-d");

    @Test
    public void testWrite_success() {

        SurveyCSVParser.SurveyCSVData surveyData = buildSampleData();

        JSONWriter writerOfJson = new JSONWriter(surveyData);

        try {
            String jsonString = writerOfJson.write();
            assertNotNull(jsonString);
            assertTrue(jsonString.length() > 0);
        }
        catch (JsonProcessingException e) {
            fail("JSON processing failed");
        }
    }

    private SurveyCSVParser.SurveyCSVData buildSampleData() {

        SurveyCSVParser.SurveyCSVData surveyData = new SurveyCSVParser.SurveyCSVData(SurveyCSVParser.SurveyCSVData.Employee.SortOrder.ORIGINAL);

        SurveyCSVParser.SurveyCSVData.Division division = new SurveyCSVParser.SurveyCSVData.Division(1, SurveyCSVParser.SurveyCSVData.Employee.SortOrder.ORIGINAL);
        SurveyCSVParser.SurveyCSVData.Team team = division.createTeam(1);
        SurveyCSVParser.SurveyCSVData.Manager manager = team.createManager(1, CSVData.SortDirection.ASCENDING);
        SurveyCSVParser.SurveyCSVData.Employee employee = manager.createEmployee(1, "Stuart", "Mackintosh", LocalDate.now().minusDays(1).format(FORMATTER));

        manager.addEmployee(1, employee);
        team.addManager(1, manager);
        division.addTeam(1, team);
        surveyData.addDivision(1, division);

        return surveyData;
    }
}

SurveyAnalyzerTests.java

代码语言:javascript
复制
package org.challenge.analysis;

import static org.junit.Assert.*;

import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.Optional;

import org.challenge.csv.CSVData;
import org.challenge.csv.survey.SurveyCSVParser;

import org.junit.Test;

public class SurveyAnalyzerTests {

    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-M-d");

    @Test
    public void test_CompanyScope_success() throws AgeCalculator.AgeCalculatorException {

        SurveyCSVParser.SurveyCSVData surveyData = buildSampleData();

        SurveyAnalyzer analysis = new SurveyAnalyzer(surveyData);
        Period period = analysis.getAverageAge(AgeCalculator.Scope.COMPANY, Optional.empty());
        assertNotNull(period);
        assertEquals(1, period.getDays());      
    }

    @Test
    public void test_NoEmployees_success() throws AgeCalculator.AgeCalculatorException {

        SurveyCSVParser.SurveyCSVData surveyData = buildEmptySampleData();

        SurveyAnalyzer analysis = new SurveyAnalyzer(surveyData);
        Period period = analysis.getAverageAge(AgeCalculator.Scope.COMPANY, Optional.empty());
        assertNotNull(period);
        assertTrue(period.equals(Period.ZERO));     
    }

    @Test
    public void test_DivisionScope_success() throws AgeCalculator.AgeCalculatorException {

        SurveyCSVParser.SurveyCSVData surveyData = buildSampleData();

        SurveyAnalyzer analysis = new SurveyAnalyzer(surveyData);
        Period period = analysis.getAverageAge(AgeCalculator.Scope.DIVISION, Optional.of(1));
        assertNotNull(period);
        assertEquals(1, period.getDays());      
    }

    @Test(expected=AgeCalculator.AgeCalculatorException.class)
    public void test_DivisionScope_failure() throws AgeCalculator.AgeCalculatorException {

        SurveyCSVParser.SurveyCSVData surveyData = buildEmptySampleData();

        SurveyAnalyzer analysis = new SurveyAnalyzer(surveyData);
        analysis.getAverageAge(AgeCalculator.Scope.DIVISION, null);     
    }

    private SurveyCSVParser.SurveyCSVData buildSampleData() {

        SurveyCSVParser.SurveyCSVData surveyData = new SurveyCSVParser.SurveyCSVData(SurveyCSVParser.SurveyCSVData.Employee.SortOrder.ORIGINAL);

        SurveyCSVParser.SurveyCSVData.Division division = new SurveyCSVParser.SurveyCSVData.Division(1, SurveyCSVParser.SurveyCSVData.Employee.SortOrder.ORIGINAL);
        SurveyCSVParser.SurveyCSVData.Team team = division.createTeam(1);
        SurveyCSVParser.SurveyCSVData.Manager manager = team.createManager(1, CSVData.SortDirection.ASCENDING);
        SurveyCSVParser.SurveyCSVData.Employee employee1 = manager.createEmployee(1, "Stuart", "Mackintosh", LocalDate.now().minusDays(1).format(FORMATTER));
        SurveyCSVParser.SurveyCSVData.Employee employee2 = manager.createEmployee(2, "Stuart L", "Mackintosh", LocalDate.now().minusDays(2).format(FORMATTER));

        manager.addEmployee(1, employee1);
        manager.addEmployee(2, employee2);
        team.addManager(1, manager);
        division.addTeam(1, team);
        surveyData.addDivision(1, division);

        return surveyData;
    }

    private SurveyCSVParser.SurveyCSVData buildEmptySampleData() {

        SurveyCSVParser.SurveyCSVData surveyData = new SurveyCSVParser.SurveyCSVData(SurveyCSVParser.SurveyCSVData.Employee.SortOrder.ORIGINAL);

        SurveyCSVParser.SurveyCSVData.Division division = new SurveyCSVParser.SurveyCSVData.Division(1, SurveyCSVParser.SurveyCSVData.Employee.SortOrder.ORIGINAL);
        SurveyCSVParser.SurveyCSVData.Team team = division.createTeam(1);
        SurveyCSVParser.SurveyCSVData.Manager manager = team.createManager(1, CSVData.SortDirection.ASCENDING);

        team.addManager(1, manager);
        division.addTeam(1, team);
        surveyData.addDivision(1, division);

        return surveyData;      
    }
}

Data.csv (节选):

代码语言:javascript
复制
divisionId,teamId,managerId,employeeId,firstName,lastName,birthdate
7,6,2,597,Terrill,Lindgren,1956-7-21
7,10,2,632,Cecile,Mante,1955-3-11
6,2,1,489,Audreanne,Labadie,1964-4-5
9,9,1,859,Vinnie,Mann,1974-11-20
7,7,1,607,Cecilia,Kunde,1997-7-18
2,9,2,134,Taryn,Bednar,1970-5-8
9,9,2,865,Helmer,Littel,1964-2-19
11,4,1,1071,Declan,Bailey,1972-8-7
5,8,1,476,Gladyce,Mills,1988-12-15
12,3,1,1157,Cyrus,Tillman,1980-2-19
7,12,2,651,Camryn,Ernser,1965-11-17
6,4,1,515,Kadin,Wehner,1989-11-5
7,4,1,570,Kirk,Rowe,1966-1-26
10,6,1,993,Ashlee,Wuckert,1956-1-9
13,2,2,1183,Anibal,Botsford,1972-7-25
7,6,2,598,Roscoe,Corkery,1954-5-16
10,7,1,1008,Branson,Hammes,1983-5-2
14,9,1,1308,Favian,Skiles,1981-9-13
14,10,1,1331,Kaelyn,Rosenbaum,1956-8-22
8,9,1,765,Shea,Osinski,1964-3-5
7,6,2,594,Helena,Lesch,1957-10-26
9,9,2,864,Orrin,Stiedemann,1951-10-19
5,8,1,475,Vivien,Kemmer,1981-7-20
5,3,1,432,Genoveva,Kassulke,1987-5-27
8,5,2,745,Verdie,Gerhold,1988-6-25
1,5,2,15,Stefan,Stokes,1978-11-24
8,4,1,731,Tyrel,McDermott,1992-12-9
2,10,1,139,Rickey,Hodkiewicz,1968-1-24
10,8,1,1017,Gianni,Morissette,1992-8-23
14,11,2,1342,Uriel,Halvorson,1965-9-9
7,10,2,630,Robert,Johnston,1955-10-27
14,12,2,1366,Rene,Carter,1988-9-23
2,1,1,51,Maggie,O'Kon,1998-5-22
2,11,1,156,Jerod,Walker,1971-8-3
13,2,1,1174,Margarette,Jacobi,1955-8-10
3,12,1,301,Cleo,Hudson,1989-1-28
2,13,1,183,Jaquan,Skiles,1957-9-10
9,13,1,904,Elfrieda,Langworth,1953-10-18
5,7,1,461,Torrey,Gislason,1998-1-23
2,7,1,102,Demond,Herman,1950-7-3
11,3,1,1057,Gracie,Rau,1957-6-9
14,7,1,1290,Ollie,Bogan,1951-10-4
7,8,1,610,Rahul,Spencer,1981-10-3
8,5,2,742,Bell,Orn,1963-8-19
8,6,1,752,Alisa,Corwin,1969-11-4
3,2,1,198,Angelina,Corwin,1969-2-2
3,5,2,243,Rigoberto,Runolfsson,1971-1-21
9,16,1,934,Elise,Hegmann,1964-2-5
9,17,1,935,Richmond,Cormier,1980-1-6
14,5,2,1273,Eino,O'Conner,1969-8-24
13,7,1,1214,Kathryn,Kub,1966-1-6
5,7,2,470,Golden,Reichert,1952-9-10
2,1,1,57,Dejah,Schaefer,1975-2-5
2,7,1,101,Ronny,McCullough,1994-6-2
10,6,2,1001,Nikki,Runolfsson,1961-10-5
8,4,1,730,Wayne,Ward,1997-4-9
7,3,1,569,Vivian,Muller,1969-7-31
5,6,1,450,Juvenal,Schmidt,1973-8-5
14,5,2,1274,Orrin,O'Keefe,1981-12-13
14,9,1,1313,Jazlyn,Walter,1992-4-13
1,4,1,7,Darwin,Collins,1975-4-11
9,13,1,901,Margarita,Spinka,1972-5-4
10,2,1,954,Stephen,Schmitt,1980-2-5
2,7,1,104,Westley,Swift,1989-10-19
3,14,1,321,Emelie,Simonis,1951-5-29
11,11,2,1126,Clement,Lemke,1990-10-20
7,14,2,680,Millie,Haag,1979-8-23
2,1,1,56,Marcelino,Will,1987-10-29
14,7,1,1288,Cheyanne,Labadie,1954-7-20
4,3,2,386,Owen,Turner,1986-2-7
3,1,1,193,Lynn,Huel,1963-8-17
14,11,2,1345,Evangeline,Becker,1995-10-9
6,6,1,535,Bridget,Rath,1959-9-12
3,10,1,277,Rodolfo,O'Kon,1951-3-30
12,2,1,1153,Vincent,Collins,1991-8-17
12,1,2,1145,Coralie,Olson,1956-9-14
9,16,1,933,Annabell,Wehner,1965-5-25
7,12,2,649,Davonte,Kohler,1970-6-30
2,12,1,170,Laury,Muller,1968-12-16
7,9,2,622,Norval,Gusikowski,1967-5-18
2,12,1,173,Jena,Conn,1999-5-23
11,3,1,1056,Kamren,Koch,1960-3-24
14,1,1,1242,Mckenna,Graham,1958-6-20
12,3,1,1155,Raegan,Doyle,1996-12-9
9,17,1,939,Lazaro,Swaniawski,1981-8-16
10,4,2,974,Astrid,Rath,1998-9-19
3,4,1,215,Scarlett,Watsica,1987-5-27
5,1,1,400,Jenifer,Stokes,1969-5-16
12,3,2,1164,Kobe,Wisozk,1958-3-24
8,11,1,788,Margret,Zemlak,1993-8-20
9,15,1,920,Sister,Braun,1960-11-9
5,1,1,402,Daniela,Pollich,1968-11-11
9,4,2,820,Cornell,Robel,1952-4-9
3,4,2,227,Marion,Flatley,1997-11-13
1,4,1,3,Arvel,Runolfsdottir,1954-9-5
6,3,1,498,Jazmyn,Hartmann,1986-9-4
5,3,1,433,Cloyd,Botsford,1995-12-23
9,16,1,932,Jerrell,Moore,1972-12-3
11,4,1,1072,Jefferey,Goldner,1984-5-3
14,5,1,1267,Nicolas,Davis,1988-2-5
14,7,1,1291,Demarco,Rolfson,1980-1-3
6,1,1,483,Katelin,Hintz,1955-3-2
14,11,1,1339,Jennings,Schowalter,1985-8-6
12,3,2,1159,Kamryn,Wyman,1998-8-17
3,1,1,187,Tremayne,Cummings,1998-1-14
3,13,1,316,D'angelo,Morar,1990-10-20
3,16,1,346,Marian,Mante,1955-2-27
7,13,1,664,Audreanne,Schoen,1987-9-16
14,2,1,1245,Rylan,Conroy,1951-6-8
5,3,1,429,Leola,Hansen,1997-5-6
10,6,1,991,Ahmad,Schinner,1966-2-11
6,6,1,536,Irma,Osinski,1988-11-29
13,2,1,1173,Sister,Heller,1984-9-13
10,8,1,1019,Margaret,Stokes,1960-8-8
14,11,2,1347,Noah,Brakus,1983-4-21
9,5,1,827,Christina,Feeney,1972-5-31
2,12,1,172,Elwyn,Upton,1971-11-9
2,10,1,143,Reva,Hand,1955-3-17
7,7,1,605,Evangeline,Schuster,1995-7-20
6,5,2,529,Albina,Koss,1981-2-12
7,16,1,698,Ronaldo,Rutherford,1983-11-22
9,12,2,899,Odessa,McClure,1958-6-5
3,4,2,219,Braulio,Gibson,1960-6-12
13,8,2,1232,Josiah,Reynolds,1963-7-30
3,5,1,229,Vidal,Schuppe,1963-2-12
2,1,1,50,Friedrich,Ortiz,1951-1-30
13,4,2,1199,Orin,Vandervort,1981-4-17
3,2,1,196,Chelsey,Boyer,1995-9-5
14,5,2,1276,Tracy,Leffler,1983-3-31
12,3,2,1161,Edythe,Sauer,1972-2-1
13,3,1,1186,Otilia,O'Reilly,1986-2-20
4,4,2,394,Taylor,Quitzon,1975-8-16
11,10,2,1112,Kayli,Mohr,1961-10-10
10,2,1,950,Tillman,Abshire,1972-11-11
13,3,2,1190,Nya,Klocko,1971-6-10
9,14,1,913,Pedro,D'Amore,1957-10-19
12,3,2,1165,Gunner,Hamill,1986-9-15
7,3,1,566,Bailey,Bayer,1965-2-7
3,15,1,339,Broderick,Hettinger,1998-6-18
14,10,1,1326,Carlos,Von,1978-10-21
3,16,2,349,Webster,Rodriguez,1987-7-2
3,16,1,348,Vallie,Wyman,1995-3-16
14,9,2,1318,Clifford,Leuschke,1959-8-30
7,8,1,612,Otto,Mante,1951-3-26
3,8,1,267,Kaleb,Rice,1963-12-25
9,17,1,942,Dave,Erdman,1968-5-23
14,4,1,1263,Lemuel,Osinski,1966-4-20
14,7,2,1292,Winnifred,Mraz,1964-11-29
11,9,1,1093,Ottilie,Gutmann,1990-11-2
9,3,1,797,Rocio,Fisher,1960-2-21
2,10,1,147,Tobin,Larkin,1987-12-27
11,3,1,1058,Brenden,Bechtelar,1981-8-2
13,8,1,1228,Irma,Bruen,1972-8-21
11,1,1,1043,Francisco,Hartmann,1967-6-4
4,3,1,377,Donato,Hyatt,1955-4-21
5,3,1,428,Alexanne,Parker,1965-1-9
11,1,1,1041,Eleanora,Littel,1985-4-19
7,14,1,674,Curt,Kshlerin,1996-12-2
11,10,2,1107,Yazmin,Williamson,1971-5-25
3,12,1,305,Bailee,Rodriguez,1965-5-14
11,2,1,1052,Mathew,McClure,1960-10-18
14,9,2,1317,Macie,Rath,1971-11-6
9,3,2,805,Joany,Sanford,1972-1-24
1,6,1,20,Manley,Bednar,1973-5-31
4,1,2,369,Twila,Stoltenberg,1981-8-8
1,3,2,1,Maeve,Corwin,1963-4-7
11,5,1,1075,Effie,Dooley,1997-6-28
14,4,1,1261,Whitney,Gibson,1982-8-16
2,8,1,117,Chris,Mann,1992-3-2
10,8,1,1014,Hans,Hauck,1953-10-29
10,5,1,979,Wilfredo,Kub,1993-1-9
5,6,1,446,Gabe,Walter,1954-9-23
3,2,1,197,Maxine,Oberbrunner,1996-8-8
9,12,1,888,Cecile,Adams,1963-7-23
2,11,1,153,Tyree,Lemke,1983-8-7
2,11,1,149,Mathew,Lehner,1967-12-3
1,5,1,11,Hipolito,Collins,1961-12-17
7,1,1,548,Assunta,Murazik,1993-5-27
1,7,1,31,Maye,Torphy,1956-12-11
8,9,1,767,Kamille,Kessler,1995-11-27
4,3,1,380,Derrick,Bergnaum,1996-4-20
11,9,2,1096,Hal,Price,1970-11-29
8,1,1,705,Jailyn,Predovic,1993-6-7
10,2,1,958,Jamaal,Buckridge,1997-4-12
14,1,1,1240,Dovie,Yundt,1995-8-17
8,8,1,760,Marisol,Beahan,1975-6-25
3,6,2,248,Jade,Haag,1950-10-21
13,8,1,1223,Gerry,Ziemann,1976-4-3
14,1,1,1237,Logan,Schneider,1977-5-31
7,16,1,700,Nikki,Daniel,1978-4-28
10,5,2,989,Art,Bernhard,1969-9-28
14,1,1,1234,Cassie,Aufderhar,1990-8-31
9,12,2,898,Kayden,Spinka,1986-1-9
11,3,2,1063,Faustino,Schamberger,1994-11-14
6,3,2,509,April,Williamson,1984-4-21
10,4,1,971,Cristina,DuBuque,1968-9-19
9,14,1,911,Roel,Flatley,1958-10-17
7,5,1,578,Magdalena,Cole,1986-2-23
8,3,1,718,Pat,Dach,1956-2-29
9,15,2,923,Kiana,Jenkins,1994-7-28
11,1,1,1042,Gene,West,1953-5-21
13,1,1,1170,Adelbert,Lockman,1991-10-11
1,4,1,4,Anthony,Armstrong,1957-4-9
1,7,2,35,Ramiro,Kohler,1973-9-6
14,5,2,1275,Reyes,Funk,1960-6-10
14,11,1,1334,Ellis,Roob,1951-9-18
2,9,2,138,Linnea,Blanda,1968-2-29
2,4,2,85,Elinor,Jakubowski,1999-4-29
9,13,2,909,Kristy,Orn,1963-12-9
9,12,1,893,Mandy,Howell,1985-11-9
14,6,1,1281,Marisa,Terry,1991-2-12
12,1,1,1133,Taryn,Predovic,1990-9-19
11,7,2,1083,Otto,Bergstrom,1955-6-8
14,11,2,1343,Howell,Moore,1956-9-27
11,3,2,1061,Sabina,Senger,1968-4-1
1,8,2,45,Gaston,Graham,1963-9-2
9,17,1,941,Brant,Halvorson,1970-12-28
3,11,2,292,Hallie,Schaefer,1974-8-6
9,6,1,832,Kara,Block,1974-2-5
4,4,1,390,Terrence,Effertz,1986-11-29
4,1,1,356,Maye,Bauch,1980-9-16
2,6,2,96,Brock,Rowe,1971-1-17
7,4,1,575,Jessie,Larkin,1977-6-24
14,4,1,1260,Carlie,Gerlach,1995-5-11
1,7,2,33,Kirsten,Reichel,1988-11-6
3,9,1,271,Roselyn,Jakubowski,1970-11-19
14,12,1,1360,Alene,Jacobi,1999-5-26
10,5,2,986,Newton,Volkman,1969-12-13
7,13,1,656,Soledad,Spencer,1993-12-31
3,5,1,230,Lucas,Emmerich,1977-9-29
14,8,2,1307,Lyla,Vandervort,1979-6-16
10,3,1,969,Vena,Conn,1985-3-6
9,11,1,877,Sally,Runolfsdottir,1960-10-6
11,11,1,1121,Caroline,Smitham,1979-8-4
9,1,1,792,Litzy,Tromp,1972-8-22
7,10,2,631,Reynold,Dare,1991-4-14
10,7,2,1011,Beverly,McLaughlin,1999-8-20
1,6,1,18,Jaylen,Cole,1975-10-6
2,13,1,182,Delia,Strosin,1968-11-29
8,9,1,764,Lavina,Koch,1993-9-16
2,4,2,87,Marvin,Lehner,1956-11-1
10,2,1,956,Prince,Schroeder,1979-5-9
2,9,1,129,Emmie,Auer,1969-6-19
8,5,2,743,Antoinette,Legros,1986-5-17
9,7,1,847,Murphy,Jenkins,1955-12-2
11,11,2,1124,Quinton,Romaguera,1973-12-28
12,3,2,1166,Martine,Stanton,1977-3-1
8,4,2,737,Nova,Sporer,1993-4-5
3,13,1,314,Gilberto,Kuhic,1970-4-17
10,1,2,948,Faye,Wisoky,1958-12-11
7,12,2,650,Aleen,O'Connell,1987-9-21
10,5,1,975,Sandrine,Hegmann,1980-6-27
4,3,1,379,Shanna,Mann,1977-7-4
1,5,2,14,Eugenia,Nicolas,1976-5-5
13,2,1,1175,Heaven,Lang,1962-12-29
7,6,1,593,Hans,Fahey,1964-3-30
3,14,2,330,Alexa,Muller,1964-12-20
7,9,2,616,Elwyn,Russel,1966-5-21
10,2,1,953,Adolphus,Koch,1975-7-25
9,10,1,870,Rose,Walker,1950-6-15
3,3,2,212,Jairo,Smith,1980-11-5
8,11,1,781,Haylee,Stiedemann,1980-12-8
2,8,1,118,Alysson,Wisoky,1982-10-2
13,7,1,1217,Jace,Monahan,1995-12-10
14,5,2,1278,Danny,Kautzer,1967-12-30
1,6,2,26,Madyson,Bednar,1972-5-27
11,1,2,1047,Annalise,Lind,1982-7-23
1,5,2,13,Orlo,Wuckert,1991-2-14
9,15,2,924,Nicole,Balistreri,1950-10-5
7,6,2,596,Abigayle,Bogisich,1977-7-4
8,2,1,713,Malcolm,Spencer,1982-11-24
10,1,2,949,Eugene,Barrows,1983-7-30
6,6,2,546,Edward,Crist,1996-4-30
9,8,1,856,Percival,Bogan,1968-2-16
2,7,2,109,Gaetano,Rosenbaum,1979-1-30
14,11,2,1349,Eulalia,Nader,1958-4-18
1,8,1,37,Remington,Ratke,1988-11-15
7,15,1,687,Vada,Hansen,1960-10-13
4,3,2,387,Rogers,Larkin,1988-7-20
5,2,1,419,Arne,Ernser,1971-1-24
4,2,1,372,Orin,Quitzon,1995-1-26
11,9,2,1099,Roscoe,Collier,1990-6-1
13,7,1,1218,Chet,Wyman,1953-7-13
2,3,2,67,Aubree,Marvin,1979-6-6
3,15,1,337,Clare,Runolfsson,1969-9-9
14,11,2,1348,Urban,Hamill,1963-2-12
9,7,2,848,Hulda,Kautzer,1971-7-29
5,2,2,424,Neha,Jenkins,1961-8-22
3,4,1,214,Shawna,Boyle,1991-12-11
10,7,2,1012,Ivory,Davis,1987-5-16
11,8,1,1085,Esteban,Powlowski,1954-12-25
8,9,2,773,Dannie,Bogisich,1949-11-2
8,9,1,768,Aylin,Sporer,1990-12-30
2,2,1,59,Tianna,Kilback,1995-11-19
13,8,1,1226,Verla,Lehner,1969-4-14
2,12,1,169,Tina,Becker,1966-8-5
12,1,2,1142,Cassie,Littel,1956-10-4
5,3,1,430,Naomi,Stiedemann,1953-11-24
10,5,2,987,Deonte,Larson,1980-3-5
2,6,2,95,Odie,Halvorson,1992-11-5
2,13,1,181,Yolanda,Leannon,1996-3-2
10,5,1,980,Rachel,West,1978-3-24
8,10,2,777,Gladys,Lakin,1978-8-23
12,3,1,1156,Eugene,Farrell,1975-2-22
7,13,2,668,Ryley,Berge,1989-11-3
14,10,1,1324,Martine,Becker,1961-4-15
6,1,1,484,Greyson,Welch,1956-3-7
3,3,1,205,Cade,Hessel,1990-2-5
13,3,1,1188,Federico,Bins,1976-6-29
1,4,1,2,Lauren,Keeling,1969-12-27
2,10,1,144,Brandt,Torp,1960-8-1
10,2,1,951,Joey,Abernathy,1973-3-20
3,3,2,209,Alayna,Orn,1988-7-28
4,1,1,359,Jensen,Beier,1956-12-9
3,5,2,238,Victor,Murray,1983-6-3
2,11,2,167,Lauriane,Hodkiewicz,1952-2-25
9,13,1,906,Mayra,Heidenreich,1969-9-8
14,4,1,1257,Ova,Torp,1955-12-26
11,10,2,1111,Verla,Oberbrunner,1959-7-9
3,14,2,327,Brianne,Schoen,1975-7-29
7,1,2,559,Agustin,Pouros,1997-3-25
10,6,2,999,Earline,Becker,1964-1-22
13,2,1,1177,Genevieve,Kutch,1984-3-23
3,7,1,261,Gussie,Emmerich,1971-2-12
9,4,1,818,Louisa,Strosin,1953-8-16
10,5,2,985,Okey,Fisher,1960-12-2
2,13,1,179,Aylin,Kshlerin,1967-10-21
10,3,1,966,Sonya,Hagenes,1977-5-13
14,11,1,1338,Murl,Boehm,1986-2-4
7,5,2,581,Jamie,Aufderhar,1990-12-28
2,12,1,168,Keegan,Collins,1978-8-24
7,13,1,657,Connor,Kessler,1981-7-1
11,8,2,1091,Lauren,Hoeger,1958-1-1
10,4,1,970,Martina,Greenholt,1978-10-20
5,8,1,472,Clinton,Maggio,1968-5-31
9,14,1,917,Esther,Nitzsche,1989-7-24
2,10,1,142,Rashad,Ortiz,1950-3-5
4,3,2,385,Jacky,Crona,1989-6-18
12,2,1,1149,Neoma,Schamberger,1981-3-23
2,7,1,105,Giovanni,Wuckert,1989-4-28
14,4,1,1256,Zackary,Jaskolski,1961-11-14
13,4,1,1197,Sally,Stokes,1975-3-29
5,1,1,404,Terrence,Purdy,1969-6-15
7,14,1,672,Margret,Bradtke,1984-1-24
7,6,2,602,Maureen,Stark,1994-12-16
9,16,1,931,Heather,Goyette,1951-7-10
9,11,1,881,Rosario,Kohler,1969-3-24
2,6,2,98,Gerry,Daugherty,1986-6-22
2,7,2,111,Destany,Jacobs,1981-7-31
9,15,1,922,Caitlyn,Nikolaus,1949-12-16
14,5,1,1265,Fanny,Sawayn,1956-6-30
7,10,1,624,Vincenzo,Kozey,1975-10-20
7,4,1,574,Ciara,Prosacco,1958-11-14
5,7,1,465,Chandler,Borer,1957-3-12
10,6,2,998,Kraig,Ortiz,1953-8-6
5,1,1,405,Waldo,Swaniawski,1951-7-30
7,10,2,635,Jeramy,Kiehn,1981-4-10
2,8,1,119,Dedrick,Yundt,1973-2-26
2,2,1,63,Eugene,Kuhlman,1960-8-11
9,9,2,863,Dedrick,Conn,1965-5-11
14,5,1,1270,Susie,Labadie,1957-10-27
9,3,1,802,Ora,Mohr,1956-1-17
10,5,1,981,Delphine,Lindgren,1980-11-22
3,17,1,352,Chanel,Dare,1980-5-19
2,4,1,78,Shany,Kessler,1983-10-12
2,11,2,162,Loyal,Mertz,1964-11-21
8,10,1,775,Hettie,Kris,1969-1-21
14,1,1,1238,Jon,Pagac,1973-1-16
8,4,1,728,Katrina,Kovacek,1962-5-29
3,12,1,304,Jaime,Barrows,1968-2-25
14,11,1,1337,Casey,Gibson,1988-10-15
12,1,2,1140,Melany,Blanda,1978-1-11
5,2,1,415,Nelda,Hartmann,1973-8-30
10,6,1,990,Nelle,Gislason,1988-2-15
3,12,1,306,Gunnar,Hartmann,1977-7-6
11,6,1,1080,Hoyt,Nikolaus,1987-4-21
...

我的指示/答复:

Eclipse项目用于挑战

要求:

  • Java 8
  • 等级4.3
  • Jackson 2.4
  • JUnit 4.12

使用Gradle构建:

代码语言:javascript
复制
Gradlew.bat build

在/src/ main /java/org/质询/Task1.java中执行main,控制数据排序顺序和雇员排序顺序的可能参数如下:

代码语言:javascript
复制
[ORIGINAL/ID/LASTNAME/FIRSTNAME/BIRTHDATE] [ASC/DESC]

例如:

代码语言:javascript
复制
java ... org.challenge.Test1 LASTNAME DESC
java ... org.challenge.Test1 ID
java ... org.challenge.Test1

在/src/test/java/*下运行单元测试:

代码语言:javascript
复制
Gradlew.bat test

对于Javadoc:

代码语言:javascript
复制
Gradlew.bat javadoc

问题

  1. 时间复杂度为线性或O(n),没有排序,即原始,CSV文件的每一行被处理一次,映射插入和获取对于未排序的散列映射是O(1),对于排序映射是O(log )。空间复杂度为O(n)。
  2. 使用ID命令行参数获取按ID排序的所有数据,原始参数(默认)将使用CSV数据顺序。
  3. 使用ID、LASTNAME、FIRSTNAME或生日参数设置员工的排序顺序,可以选择使用ASC或DESC设置排序方向,默认为升序。
  4. 该程序将输出一些计算出的公司的平均年龄和一个样本部门,团队和经理在最后。我没有为此添加命令行参数。

假设

员工生日总是采用yyyy格式.CSV文件可以完全读入可用的堆中。格式错误的CSV行将结束解析操作。文件读取将不会被重新尝试。整数数据类型可以包含所有ID。长数据类型可以包含平均年龄计算范围内所有员工的总年龄(以天为单位)。范围内所有员工的平均年龄四舍五入到最近的一天。

EN

回答 1

Code Review用户

回答已采纳

发布于 2018-10-18 21:05:20

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/205813

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档