Skip to content

Commit 9252fe6

Browse files
committed
refactor: Refactor SJFScheduling and Tests
1 parent dba2d86 commit 9252fe6

File tree

2 files changed

+60
-155
lines changed

2 files changed

+60
-155
lines changed

src/main/java/com/thealgorithms/scheduling/SJFScheduling.java

Lines changed: 30 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,78 +2,49 @@
22

33
import com.thealgorithms.devutils.entities.ProcessDetails;
44
import java.util.ArrayList;
5+
import java.util.Comparator;
56
import java.util.List;
67

78
/**
8-
* Implementation of Shortest Job First Algorithm: The algorithm allows the waiting process with the
9-
* minimal burst time to be executed first. see more here:
10-
* https://www.guru99.com/shortest-job-first-sjf-scheduling.html
9+
* Shortest Job First (SJF) Scheduling Algorithm:
10+
* Executes processes with the shortest burst time first among the ones that have arrived.
1111
*/
12-
1312
public class SJFScheduling {
14-
protected ArrayList<ProcessDetails> processes;
15-
protected ArrayList<String> schedule;
16-
17-
private static void sortProcessesByArrivalTime(List<ProcessDetails> processes) {
18-
for (int i = 0; i < processes.size(); i++) {
19-
for (int j = i + 1; j < processes.size() - 1; j++) {
20-
if (processes.get(j).getArrivalTime() > processes.get(j + 1).getArrivalTime()) {
21-
final var temp = processes.get(j);
22-
processes.set(j, processes.get(j + 1));
23-
processes.set(j + 1, temp);
24-
}
25-
}
26-
}
27-
}
13+
private final List<ProcessDetails> processes;
14+
private final List<String> schedule;
2815

29-
/**
30-
* a simple constructor
31-
* @param processes a list of processes the user wants to schedule
32-
* it also sorts the processes based on the time of their arrival
33-
*/
34-
SJFScheduling(final ArrayList<ProcessDetails> processes) {
35-
this.processes = processes;
36-
schedule = new ArrayList<>();
16+
public SJFScheduling(final List<ProcessDetails> processes) {
17+
this.processes = new ArrayList<>(processes);
18+
this.schedule = new ArrayList<>();
3719
sortProcessesByArrivalTime(this.processes);
3820
}
39-
protected void sortByArrivalTime() {
40-
sortProcessesByArrivalTime(processes);
21+
22+
private static void sortProcessesByArrivalTime(List<ProcessDetails> processes) {
23+
processes.sort(Comparator.comparingInt(ProcessDetails::getArrivalTime));
4124
}
4225

4326
/**
44-
* this functions returns the order of the executions
27+
* Executes the SJF scheduling algorithm and builds the execution order.
4528
*/
46-
4729
public void scheduleProcesses() {
48-
ArrayList<ProcessDetails> ready = new ArrayList<>();
49-
30+
List<ProcessDetails> ready = new ArrayList<>();
5031
int size = processes.size();
51-
int runtime;
5232
int time = 0;
5333
int executed = 0;
54-
int j;
5534
int k = 0;
56-
ProcessDetails running;
57-
58-
if (size == 0) {
59-
return;
60-
}
6135

6236
while (executed < size) {
63-
while (k < size && processes.get(k).getArrivalTime() <= time) // here we find the processes that have arrived.
64-
{
37+
// Load arrived processes into ready queue
38+
while (k < size && processes.get(k).getArrivalTime() <= time) {
6539
ready.add(processes.get(k));
6640
k++;
6741
}
6842

69-
running = findShortestJob(ready);
43+
ProcessDetails running = findShortestJob(ready);
7044
if (running == null) {
7145
time++;
7246
} else {
73-
runtime = running.getBurstTime();
74-
for (j = 0; j < runtime; j++) {
75-
time++;
76-
}
47+
time += running.getBurstTime();
7748
schedule.add(running.getProcessId());
7849
ready.remove(running);
7950
executed++;
@@ -82,30 +53,25 @@ public void scheduleProcesses() {
8253
}
8354

8455
/**
85-
* this function evaluates the shortest job of all the ready processes (based on a process
86-
* burst time)
56+
* Finds the process with the shortest job of all the ready processes (based on a process
8757
* @param readyProcesses an array list of ready processes
8858
* @return returns the process' with the shortest burst time OR NULL if there are no ready
8959
* processes
9060
*/
9161
private ProcessDetails findShortestJob(List<ProcessDetails> readyProcesses) {
92-
if (readyProcesses.isEmpty()) {
93-
return null;
94-
}
95-
int i;
96-
int size = readyProcesses.size();
97-
int minBurstTime = readyProcesses.get(0).getBurstTime();
98-
int temp;
99-
int positionOfShortestJob = 0;
62+
return readyProcesses.stream()
63+
.min(Comparator.comparingInt(ProcessDetails::getBurstTime))
64+
.orElse(null);
65+
}
10066

101-
for (i = 1; i < size; i++) {
102-
temp = readyProcesses.get(i).getBurstTime();
103-
if (minBurstTime > temp) {
104-
minBurstTime = temp;
105-
positionOfShortestJob = i;
106-
}
107-
}
67+
/**
68+
* Returns the computed schedule after calling scheduleProcesses().
69+
*/
70+
public List<String> getSchedule() {
71+
return schedule;
72+
}
10873

109-
return readyProcesses.get(positionOfShortestJob);
74+
public List<ProcessDetails> getProcesses() {
75+
return List.copyOf(processes);
11076
}
11177
}
Lines changed: 30 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,49 @@
11
package com.thealgorithms.scheduling;
22

3-
import static org.junit.jupiter.api.Assertions.assertEquals;
4-
import static org.junit.jupiter.api.Assertions.assertTrue;
3+
import static org.junit.jupiter.api.Assertions.*;
54

65
import com.thealgorithms.devutils.entities.ProcessDetails;
7-
import java.util.ArrayList;
6+
import java.util.*;
7+
import java.util.stream.Stream;
8+
import org.junit.jupiter.api.DisplayName;
89
import org.junit.jupiter.api.Test;
10+
import org.junit.jupiter.params.ParameterizedTest;
11+
import org.junit.jupiter.params.provider.Arguments;
12+
import org.junit.jupiter.params.provider.MethodSource;
913

1014
class SJFSchedulingTest {
11-
private ArrayList<ProcessDetails> process;
12-
void initialisation0() {
1315

14-
process = new ArrayList<>();
15-
process.add(new ProcessDetails("1", 0, 6));
16-
process.add(new ProcessDetails("2", 1, 2));
16+
private static Stream<Arguments> schedulingTestData() {
17+
return Stream.of(Arguments.of(List.of(new ProcessDetails("1", 0, 6), new ProcessDetails("2", 1, 2)), List.of("1", "2")),
18+
Arguments.of(List.of(new ProcessDetails("1", 0, 6), new ProcessDetails("2", 1, 2), new ProcessDetails("3", 4, 3), new ProcessDetails("4", 3, 1), new ProcessDetails("5", 6, 4), new ProcessDetails("6", 5, 5)), List.of("1", "4", "2", "3", "5", "6")),
19+
Arguments.of(List.of(new ProcessDetails("1", 0, 3), new ProcessDetails("2", 1, 2), new ProcessDetails("3", 2, 1)), List.of("1", "3", "2")),
20+
Arguments.of(List.of(new ProcessDetails("1", 0, 3), new ProcessDetails("2", 5, 2), new ProcessDetails("3", 9, 1)), List.of("1", "2", "3")),
21+
Arguments.of(Collections.emptyList(), List.of()));
1722
}
18-
void initialisation1() {
1923

20-
process = new ArrayList<>();
21-
process.add(new ProcessDetails("1", 0, 6));
22-
process.add(new ProcessDetails("2", 1, 2));
23-
process.add(new ProcessDetails("3", 4, 3));
24-
process.add(new ProcessDetails("4", 3, 1));
25-
process.add(new ProcessDetails("5", 6, 4));
26-
process.add(new ProcessDetails("6", 5, 5));
27-
}
28-
29-
void initialisation2() {
30-
31-
process = new ArrayList<>();
32-
process.add(new ProcessDetails("1", 0, 3));
33-
process.add(new ProcessDetails("2", 1, 2));
34-
process.add(new ProcessDetails("3", 2, 1));
35-
}
36-
void initialisation3() {
37-
process = new ArrayList<>();
38-
process.add(new ProcessDetails("1", 0, 3));
39-
process.add(new ProcessDetails("2", 5, 2));
40-
process.add(new ProcessDetails("3", 9, 1));
41-
}
42-
@Test
43-
void constructor() {
44-
initialisation0();
45-
SJFScheduling a = new SJFScheduling(process);
46-
assertEquals(6, a.processes.get(0).getBurstTime());
47-
assertEquals(2, a.processes.get(1).getBurstTime());
24+
@ParameterizedTest(name = "Test SJF schedule: {index}")
25+
@MethodSource("schedulingTestData")
26+
void testSJFScheduling(List<ProcessDetails> inputProcesses, List<String> expectedSchedule) {
27+
SJFScheduling scheduler = new SJFScheduling(inputProcesses);
28+
scheduler.scheduleProcesses();
29+
assertEquals(expectedSchedule, scheduler.getSchedule());
4830
}
4931

5032
@Test
51-
void sort() {
52-
initialisation1();
53-
SJFScheduling a = new SJFScheduling(process);
54-
a.sortByArrivalTime();
55-
assertEquals("1", a.processes.get(0).getProcessId());
56-
assertEquals("2", a.processes.get(1).getProcessId());
57-
assertEquals("3", a.processes.get(3).getProcessId());
58-
assertEquals("4", a.processes.get(2).getProcessId());
59-
assertEquals("5", a.processes.get(5).getProcessId());
60-
assertEquals("6", a.processes.get(4).getProcessId());
61-
}
33+
@DisplayName("Test sorting by arrival order")
34+
void testProcessArrivalOrderIsSorted() {List<ProcessDetails> processes = List.of(new ProcessDetails("1", 0, 6), new ProcessDetails("2", 1, 2), new ProcessDetails("4", 3, 1), new ProcessDetails("3", 4, 3), new ProcessDetails("6", 5, 5), new ProcessDetails("5", 6, 4));
35+
SJFScheduling scheduler = new SJFScheduling(processes);
36+
List<String> actualOrder = scheduler.getProcesses().stream()
37+
.map(ProcessDetails::getProcessId)
38+
.toList();
6239

63-
@Test
64-
void scheduling() {
65-
initialisation1();
66-
SJFScheduling a = new SJFScheduling(process);
67-
a.scheduleProcesses();
68-
assertEquals("1", a.schedule.get(0));
69-
assertEquals("4", a.schedule.get(1));
70-
assertEquals("2", a.schedule.get(2));
71-
assertEquals("3", a.schedule.get(3));
72-
assertEquals("5", a.schedule.get(4));
73-
assertEquals("6", a.schedule.get(5));
40+
assertEquals(List.of("1", "2", "4", "3", "6", "5"), actualOrder);
7441
}
7542

7643
@Test
77-
void schedulingOfTwoProcesses() {
78-
initialisation0();
79-
SJFScheduling a = new SJFScheduling(process);
80-
a.scheduleProcesses();
81-
assertEquals("1", a.schedule.get(0));
82-
assertEquals("2", a.schedule.get(1));
83-
}
84-
85-
@Test
86-
void schedulingOfAShortestJobArrivingLast() {
87-
initialisation2();
88-
SJFScheduling a = new SJFScheduling(process);
89-
a.scheduleProcesses();
90-
assertEquals("1", a.schedule.get(0));
91-
assertEquals("3", a.schedule.get(1));
92-
assertEquals("2", a.schedule.get(2));
93-
}
94-
@Test
95-
void schedulingWithProcessesNotComingBackToBack() {
96-
initialisation3();
97-
SJFScheduling a = new SJFScheduling(process);
98-
a.scheduleProcesses();
99-
assertEquals("1", a.schedule.get(0));
100-
assertEquals("2", a.schedule.get(1));
101-
assertEquals("3", a.schedule.get(2));
102-
}
103-
@Test
104-
void schedulingOfNothing() {
105-
process = new ArrayList<>();
106-
SJFScheduling a = new SJFScheduling(process);
107-
a.scheduleProcesses();
108-
assertTrue(a.schedule.isEmpty());
44+
void testSchedulingEmptyList() {
45+
SJFScheduling scheduler = new SJFScheduling(Collections.emptyList());
46+
scheduler.scheduleProcesses();
47+
assertTrue(scheduler.getSchedule().isEmpty());
10948
}
11049
}

0 commit comments

Comments
 (0)