Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions java-merge-sort/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Java Merge Sort Implementation

This is a Java conversion of the COBOL merge sort example found in `../merge_sort/merge_sort_test.cbl`.

## Overview

The implementation provides equivalent functionality to the original COBOL program:

1. **CustomerRecord Class**: Represents customer data with fields matching the COBOL structure
2. **MergeSortProcessor**: Handles file operations, merging, and sorting
3. **MergeSortMain**: Main application that orchestrates the workflow

## Features

- Creates test data programmatically (matching COBOL test data)
- Merges two sorted files by customer ID in ascending order
- Sorts merged file by contract ID in descending order
- Displays results after each operation
- Proper file I/O with exception handling

## Data Structure

The `CustomerRecord` class implements `Comparable<CustomerRecord>` and contains:
- `customerId` (int) - 5-digit customer identifier
- `lastName` (String) - Customer last name (up to 50 characters)
- `firstName` (String) - Customer first name (up to 50 characters)
- `contractId` (int) - 5-digit contract identifier
- `comment` (String) - Comment field (up to 25 characters)

## Usage

### Compilation
```bash
javac -d . src/main/java/com/example/mergesort/*.java
```

### Execution
```bash
java com.example.mergesort.MergeSortMain
```

## Workflow

1. **Create Test Data**: Generates two test files with sample customer records
2. **Merge Files**: Merges the two files, sorting by customer ID ascending
3. **Sort by Contract ID**: Sorts the merged file by contract ID descending
4. **Display Results**: Shows the contents after each operation

## Files Generated

- `test-file-1.txt` - First test data file
- `test-file-2.txt` - Second test data file
- `merge-output.txt` - Merged and sorted output
- `sorted-contract-id.txt` - Final sorted output by contract ID

## Differences from COBOL Version

- Uses in-memory collections instead of direct file processing
- Leverages Java's built-in sorting capabilities
- Implements proper object-oriented design patterns
- Uses modern Java I/O APIs for file handling

## Test Data

The implementation creates the same test data as the COBOL version:

**File 1**: Customer IDs 1, 5, 10, 25, 50, 75
**File 2**: Customer IDs 3, 24, 30, 85, 999

After merging and sorting by customer ID: 1, 3, 5, 10, 24, 25, 30, 50, 75, 85, 999

After sorting by contract ID (descending): Records ordered by contract ID from highest to lowest.
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.example.mergesort;

public class CustomerRecord implements Comparable<CustomerRecord> {
private int customerId;
private String lastName;
private String firstName;
private int contractId;
private String comment;

public CustomerRecord() {
}

public CustomerRecord(int customerId, String lastName, String firstName, int contractId, String comment) {
this.customerId = customerId;
this.lastName = lastName;
this.firstName = firstName;
this.contractId = contractId;
this.comment = comment;
}

public int getCustomerId() {
return customerId;
}

public void setCustomerId(int customerId) {
this.customerId = customerId;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public int getContractId() {
return contractId;
}

public void setContractId(int contractId) {
this.contractId = contractId;
}

public String getComment() {
return comment;
}

public void setComment(String comment) {
this.comment = comment;
}

@Override
public int compareTo(CustomerRecord other) {
return Integer.compare(this.customerId, other.customerId);
}

@Override
public String toString() {
return String.format("%05d%-50s%-50s%05d%-25s",
customerId,
padRight(lastName, 50),
padRight(firstName, 50),
contractId,
padRight(comment, 25));
}

private String padRight(String str, int length) {
if (str == null) str = "";
if (str.length() >= length) {
return str.substring(0, length);
}
return str + " ".repeat(length - str.length());
}

public static CustomerRecord fromString(String line) {
if (line == null || line.length() < 135) {
throw new IllegalArgumentException("Invalid record format");
}

int customerId = Integer.parseInt(line.substring(0, 5));
String lastName = line.substring(5, 55).trim();
String firstName = line.substring(55, 105).trim();
int contractId = Integer.parseInt(line.substring(105, 110));
String comment = line.substring(110, 135).trim();

return new CustomerRecord(customerId, lastName, firstName, contractId, comment);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.example.mergesort;

import java.io.*;
import java.nio.file.*;
import java.util.*;

public class MergeSortMain {

private static final String TEST_FILE_1 = "test-file-1.txt";
private static final String TEST_FILE_2 = "test-file-2.txt";
private static final String MERGED_FILE = "merge-output.txt";
private static final String SORTED_FILE = "sorted-contract-id.txt";

private MergeSortProcessor processor;

public MergeSortMain() {
this.processor = new MergeSortProcessor();
}

public static void main(String[] args) {
MergeSortMain app = new MergeSortMain();

try {
app.createTestData();
app.mergeAndDisplayFiles();
app.sortAndDisplayFile();

System.out.println("Done.");

} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}

public void createTestData() {
System.out.println("Creating test data files...");

try {
createTestFile1();
createTestFile2();
} catch (IOException e) {
throw new RuntimeException("Failed to create test data: " + e.getMessage(), e);
}
}

private void createTestFile1() throws IOException {
List<CustomerRecord> records = Arrays.asList(
new CustomerRecord(1, "last-1", "first-1", 5423, "comment-1"),
new CustomerRecord(5, "last-5", "first-5", 12323, "comment-5"),
new CustomerRecord(10, "last-10", "first-10", 653, "comment-10"),
new CustomerRecord(50, "last-50", "first-50", 5050, "comment-50"),
new CustomerRecord(25, "last-25", "first-25", 7725, "comment-25"),
new CustomerRecord(75, "last-75", "first-75", 1175, "comment-75")
);

writeRecordsToFile(records, TEST_FILE_1);
}

private void createTestFile2() throws IOException {
List<CustomerRecord> records = Arrays.asList(
new CustomerRecord(999, "last-999", "first-999", 1610, "comment-99"),
new CustomerRecord(3, "last-03", "first-03", 3331, "comment-03"),
new CustomerRecord(30, "last-30", "first-30", 8765, "comment-30"),
new CustomerRecord(85, "last-85", "first-85", 4567, "comment-85"),
new CustomerRecord(24, "last-24", "first-24", 247, "comment-24")
);

writeRecordsToFile(records, TEST_FILE_2);
}

private void writeRecordsToFile(List<CustomerRecord> records, String fileName) throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(fileName))) {
for (CustomerRecord record : records) {
writer.write(record.toString());
writer.newLine();
}
}
}

public void mergeAndDisplayFiles() {
System.out.println("Merging and sorting files...");

processor.mergeFiles(TEST_FILE_1, TEST_FILE_2, MERGED_FILE);
processor.displayFile(MERGED_FILE, "Merged file contents:");
}

public void sortAndDisplayFile() {
System.out.println("Sorting merged file on descending contract id....");

processor.sortFileByContractId(MERGED_FILE, SORTED_FILE);
processor.displayFile(SORTED_FILE, "Sorted file contents:");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.example.mergesort;

import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.Collectors;

public class MergeSortProcessor {

public void mergeFiles(String file1Path, String file2Path, String outputPath) {
try {
List<CustomerRecord> records1 = readRecordsFromFile(file1Path);
List<CustomerRecord> records2 = readRecordsFromFile(file2Path);

Collections.sort(records1);
Collections.sort(records2);

List<CustomerRecord> mergedRecords = mergeSortedLists(records1, records2);

writeRecordsToFile(mergedRecords, outputPath);

} catch (IOException e) {
throw new RuntimeException("Error merging files: " + e.getMessage(), e);
}
}

public void sortFileByContractId(String inputPath, String outputPath) {
try {
List<CustomerRecord> records = readRecordsFromFile(inputPath);

records.sort((r1, r2) -> Integer.compare(r2.getContractId(), r1.getContractId()));

writeRecordsToFile(records, outputPath);

} catch (IOException e) {
throw new RuntimeException("Error sorting file: " + e.getMessage(), e);
}
}

private List<CustomerRecord> readRecordsFromFile(String filePath) throws IOException {
List<CustomerRecord> records = new ArrayList<>();

try (BufferedReader reader = Files.newBufferedReader(Paths.get(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
if (!line.trim().isEmpty()) {
records.add(CustomerRecord.fromString(line));
}
}
}

return records;
}

private void writeRecordsToFile(List<CustomerRecord> records, String filePath) throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(filePath))) {
for (CustomerRecord record : records) {
writer.write(record.toString());
writer.newLine();
}
}
}

private List<CustomerRecord> mergeSortedLists(List<CustomerRecord> list1, List<CustomerRecord> list2) {
List<CustomerRecord> merged = new ArrayList<>();
int i = 0, j = 0;

while (i < list1.size() && j < list2.size()) {
if (list1.get(i).compareTo(list2.get(j)) <= 0) {
merged.add(list1.get(i));
i++;
} else {
merged.add(list2.get(j));
j++;
}
}

while (i < list1.size()) {
merged.add(list1.get(i));
i++;
}

while (j < list2.size()) {
merged.add(list2.get(j));
j++;
}

return merged;
}

public void displayFile(String filePath, String description) {
try {
System.out.println(description);
List<CustomerRecord> records = readRecordsFromFile(filePath);
for (CustomerRecord record : records) {
System.out.println(record);
}
System.out.println();
} catch (IOException e) {
System.err.println("Error reading file " + filePath + ": " + e.getMessage());
}
}
}