Home > Blockchain >  Need to print sorted map value like below format in java
Need to print sorted map value like below format in java

Time:09-26

I'm sorting the Employee Data by grouping the employee number and employee salary. Excepted output I got, but I need to store this details in a fixedlength file. So I need to print by below format.

public class SortData {

    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
                      new Employee("102", "300", "100", "200"),
                      new Employee("101", "200", "80", "120"),
                      new Employee("102", "100", "50", "50"), 
                      new Employee("103", "300", "100", "200"),
                      new Employee("101", "200", "80", "120"),
                      new Employee("101", "100", "50", "50"));

        
        Map<String, Map<String, List<Employee>>> map = employees.stream()
                  .collect(Collectors.groupingBy(Employee::getEmpNo, 
    Collectors.groupingBy(Employee::getEmpSal)));
        
        System.out.println(map);
    }

}



class Employee {

    private String empNo;
    private String empSal;
    private String empHra;
    private String empPf;

    // getter
    // setter

  }

The above code's output is as below.

{101={100=[Employee(empNo=101, empSal=100, empHra=50, empPf=50)], 200=[Employee(empNo=101, 
  empSal=200, empHra=80, empPf=120), Employee(empNo=101, empSal=200, empHra=80, empPf=120)]}, 
  102={100=[Employee(empNo=102, empSal=100, empHra=50, empPf=50)], 300=[Employee(empNo=102, 
  empSal=300, empHra=100, empPf=200)]}, 
  103={300=[Employee(empNo=103, empSal=300, empHra=100, empPf=200)]}}

I need to print this out put in a fixedlength file. So I need the output as below.

1011005050
10120080120
10120080120
1021005050
102300100200
103300100200

Can anyone please help me on this.

CodePudding user response:

First, the maps in current implementation are NOT sorted.

Second, it may be redundant to sort the maps. It appears that in order to print the input data, just the input list needs to be sorted by empNo and empSal:

Comparator<Employee> sortByNoAndSal = Comparator
        .comparing(Employee::getEmpNo)
        .thenComparing(Employee::getEmpSal);

employees.sort(sortByNoAndSal);

Last, to print/output an instance of Employee specific method should be implemented (by overriding Employee::toString, or creating specific method). Aside note - required output seems to be missing a delimiter between fields of Employee.

// class PrintData
public static void printEmployee(Employee emp) {
    String delimiter = ""; // fix if necessary
    System.out.println(String.join(delimiter, emp.getNo(), emp.getSal(), emp.getHra(), emp.getPf()));
}

// invoke this method
employees.forEach(PrintData::printEmployee);

CodePudding user response:

You can use:

List<String> result = employees.stream()
            .collect(Collectors.groupingBy(Employee::getEmpNo, Collectors.groupingBy(Employee::getEmpSal)))
            .values()
            .stream()
            .flatMap(e -> buildOutput(e).stream())
            .collect(Collectors.toList());



private List<String> buildOutput(Map<String, List<Employee>> entry) {
    return entry.entrySet().stream()
            .flatMap(e -> e.getValue().stream().map(this::buildOutputForEmployee))
            .collect(Collectors.toList());
}

private String buildOutputForEmployee(Employee em) {
    return String.format("%s%s%s%s", em.getEmpNo(), em.getEmpSal(), em.getEmpHra(), em.getEmpPf());
}

to print the result:

    result.forEach(System.out::println);

Outputs:

1011005050
10120080120
10120080120
1021005050
102300100200
103300100200

CodePudding user response:

From your comments, you would like to sort by employee number and then by the employee salary.

Currently, you aren't sorting, but relying on the default ordering of the returned map type from the groupingBy operation.

1. Use a TreeMap when grouping

You can specify the type of the map to be used for groupingBy by passing a Supplier argument. Unfortunately, you also have to pass the collector in that case (toList()).

 Map<String, Map<String, List<Employee>>> map = employees.stream()
            .collect(Collectors.groupingBy(Employee::getEmpNo,
                    () -> new TreeMap<>(Comparator.comparingInt(Integer::valueOf)),
                    Collectors.groupingBy(Employee::getEmpSal,
                            () -> new TreeMap<>(Comparator.comparingInt(Integer::valueOf)),
                            Collectors.toList())));

I'm using a comparator to sort by the integer value of the employee number and salary in the TreeMap1.

You can print it as (in your case, you will be writing each record into a file).

map.entrySet()
        .stream()
        .flatMap(entry -> entry.getValue().entrySet().stream())
        .flatMap(innerEntry -> innerEntry.getValue().stream())
        .forEach(emp -> System.out.println(buildRecord(emp)));

where buildRecord just concatenates the field of the Employee class.

private static String buildRecord(Employee employee) {
    return new StringBuilder()
            .append(employee.getEmpNo())
            .append(employee.getEmpSal())
            .append(employee.getEmpHra())
            .append(employee.getEmpPf())
            .toString();
}

2. Sort the list

But there is no need to group and operate on a complicated data structure. You can simply sort it using a comparator.

employees.sort(Comparator.<Employee>comparingInt(emp -> Integer.parseInt(emp.getEmpNo()))
            .thenComparingInt(emp -> Integer.parseInt(emp.getEmpSal())));

This sorts the employees list by employee id/number and then by salary 1.

Print it as,

employees.forEach(employee -> System.out.println(buildRecord(employee)));

1 - This assumes the employee number and salary are integers. You can change it as per your need.

  • Related