Repository: TheAlgorithms/Java
Pull request #5448 (2024-09-10 22:55:08)

Refactor ProcessDetails and PreemptivePriorityScheduling
<!--
Thank you for your contribution!
In order to reduce the number of notifications sent to the maintainers, please:
- create your PR as draft, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests,
- make sure that all of the CI checks pass,
- mark your PR as ready for review, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review
-->

<!-- For completed items, change [ ] to [x] -->

- [x] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md).
- [x] This pull request is all my own work -- I have not plagiarized it.
- [x] All filenames are in PascalCase.
- [x] All functions and variable names follow Java naming conventions.
- [x] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations.
- [x] All new code is formatted with `clang-format -i --style=file path/to/your/file.java`

## Changes

Removed internal Process class from PreemptivePriorityScheduling
Updated PreemptivePriorityScheduling to use ProcessDetails from com.thealgorithms.devutils.entities
Modified PreemptivePrioritySchedulingTest to work with ProcessDetails
Updated ProcessDetails to include a priority field and relevant constructor

## Motivation
This change brings PreemptivePriorityScheduling in line with other scheduling algorithms in the project (FCFSScheduling, RRScheduling, SJFScheduling, SRTFScheduling) which all use the common ProcessDetails class. This improves consistency across the codebase and makes it easier to maintain and extend the scheduling algorithms.
Implementation Details

The Process class previously defined within PreemptivePriorityScheduling has been removed.
PreemptivePriorityScheduling now uses ProcessDetails for all process-related operations.
The priority field has been added to ProcessDetails along with getter and setter methods.
A new constructor has been added to ProcessDetails to include the priority when creating a new process.
The scheduling logic in PreemptivePriorityScheduling has been updated to work with ProcessDetails objects.
Test cases in PreemptivePrioritySchedulingTest have been updated to use ProcessDetails.

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5448?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 52.05%. Comparing base [(`65e3264`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/65e32641fc96012ae840ebc93eb2176589527783?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) to head [(`7e43774`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/7e437749e4d4a64ea43845b109f5c10ebbacfe62?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff              @@
##             master    #5448      +/-   ##
============================================
+ Coverage     52.00%   52.05%   +0.05%     
- Complexity     3235     3239       +4     
============================================
  Files           524      524              
  Lines         15169    15177       +8     
  Branches       2889     2889              
============================================
+ Hits           7889     7901      +12     
+ Misses         6957     6954       -3     
+ Partials        323      322       -1     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5448?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).

alxkm: Thank you for your contribution

Patch:
diff --git a/src/main/java/com/thealgorithms/devutils/entities/ProcessDetails.java b/src/main/java/com/thealgorithms/devutils/entities/ProcessDetails.java
index 388fb3fd..b8b863ed 100644
--- a/src/main/java/com/thealgorithms/devutils/entities/ProcessDetails.java
+++ b/src/main/java/com/thealgorithms/devutils/entities/ProcessDetails.java
@@ -6,6 +6,14 @@ public class ProcessDetails {
     private int burstTime;
     private int waitingTime;
     private int turnAroundTime;
+    private int priority;
+
+    public ProcessDetails(final String processId, final int arrivalTime, final int burstTime, int priority) {
+        this.processId = processId;
+        this.arrivalTime = arrivalTime;
+        this.burstTime = burstTime;
+        this.priority = priority;
+    }
 
     public ProcessDetails(final String processId, final int arrivalTime, final int burstTime) {
         this.processId = processId;
@@ -33,6 +41,10 @@ public class ProcessDetails {
         return turnAroundTime;
     }
 
+    public int getPriority() {
+        return priority;
+    }
+
     public void setProcessId(final String processId) {
         this.processId = processId;
     }
diff --git a/src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java b/src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java
index 9bcd5df8..27d85a94 100644
--- a/src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java
+++ b/src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java
@@ -1,5 +1,6 @@
 package com.thealgorithms.scheduling;
 
+import com.thealgorithms.devutils.entities.ProcessDetails;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
@@ -7,44 +8,35 @@ import java.util.PriorityQueue;
 
 /**
  * Preemptive Priority Scheduling Algorithm
+ *
  * @author [Bama Charan Chhandogi](https://www.github.com/BamaCharanChhandogi)
  */
+public class PreemptivePriorityScheduling {
+    protected final List<ProcessDetails> processes;
+    protected final List<String> ganttChart;
 
-class Process {
-    String name;
-    int arrivalTime;
-    int burstTime;
-    int priority;
-
-    Process(String name, int arrivalTime, int burstTime, int priority) {
-        this.name = name;
-        this.arrivalTime = arrivalTime;
-        this.burstTime = burstTime;
-        this.priority = priority;
+    public PreemptivePriorityScheduling(List<ProcessDetails> processes) {
+        this.processes = new ArrayList<>(processes);
+        this.ganttChart = new ArrayList<>();
     }
-}
 
-public final class PreemptivePriorityScheduling {
-    private PreemptivePriorityScheduling() {
-    }
-    public static List<String> preemptivePriorityScheduling(List<Process> processes) {
-        List<String> ganttChart = new ArrayList<>();
-        PriorityQueue<Process> readyQueue = new PriorityQueue<>(Comparator.comparingInt(p -> - p.priority));
+    public void scheduleProcesses() {
+        PriorityQueue<ProcessDetails> readyQueue = new PriorityQueue<>(Comparator.comparingInt(ProcessDetails::getPriority).reversed().thenComparingInt(ProcessDetails::getArrivalTime));
 
         int currentTime = 0;
+        List<ProcessDetails> arrivedProcesses = new ArrayList<>();
 
         while (!processes.isEmpty() || !readyQueue.isEmpty()) {
-            while (!processes.isEmpty() && processes.get(0).arrivalTime <= currentTime) {
-                readyQueue.add(processes.remove(0));
-            }
+            updateArrivedProcesses(currentTime, arrivedProcesses);
+            readyQueue.addAll(arrivedProcesses);
+            arrivedProcesses.clear();
 
             if (!readyQueue.isEmpty()) {
-                Process currentProcess = readyQueue.poll();
+                ProcessDetails currentProcess = readyQueue.poll();
+                ganttChart.add(currentProcess.getProcessId());
+                currentProcess.setBurstTime(currentProcess.getBurstTime() - 1);
 
-                ganttChart.add(currentProcess.name);
-                currentProcess.burstTime--;
-
-                if (currentProcess.burstTime > 0) {
+                if (currentProcess.getBurstTime() > 0) {
                     readyQueue.add(currentProcess);
                 }
             } else {
@@ -53,7 +45,15 @@ public final class PreemptivePriorityScheduling {
 
             currentTime++;
         }
+    }
 
-        return ganttChart;
+    private void updateArrivedProcesses(int currentTime, List<ProcessDetails> arrivedProcesses) {
+        processes.removeIf(process -> {
+            if (process.getArrivalTime() <= currentTime) {
+                arrivedProcesses.add(process);
+                return true;
+            }
+            return false;
+        });
     }
 }


Test patch:
diff --git a/src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java b/src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java
index 1c8a25df..d0005dda 100644
--- a/src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java
+++ b/src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java
@@ -2,32 +2,29 @@ package com.thealgorithms.scheduling;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import java.util.ArrayList;
-import java.util.Arrays;
+import com.thealgorithms.devutils.entities.ProcessDetails;
 import java.util.List;
-import org.junit.jupiter.api.Test;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 /**
  * Test Cases of Preemptive Priority Scheduling Algorithm
+ *
  * @author [Bama Charan Chhandogi](https://www.github.com/BamaCharanChhandogi)
  */
 class PreemptivePrioritySchedulingTest {
+    @ParameterizedTest
+    @MethodSource("provideProcessesAndExpectedSchedules")
+    void testPreemptivePriorityScheduling(List<ProcessDetails> processes, List<String> expectedSchedule) {
+        PreemptivePriorityScheduling scheduler = new PreemptivePriorityScheduling(processes);
+        scheduler.scheduleProcesses();
+        assertEquals(expectedSchedule, scheduler.ganttChart);
+    }
 
-    @Test
-    void testPreemptivePriorityScheduling() {
-        // Arrange
-        List<Process> processes = new ArrayList<>();
-        processes.add(new Process("P1", 0, 5, 10));
-        processes.add(new Process("P2", 1, 4, 20));
-        processes.add(new Process("P3", 2, 2, 30));
-        processes.add(new Process("P4", 4, 1, 40));
-
-        List<String> expectedGanttChart = Arrays.asList("P1", "P2", "P3", "P3", "P4", "P2", "P2", "P2", "P1", "P1", "P1", "P1");
-
-        // Act
-        List<String> actualGanttChart = PreemptivePriorityScheduling.preemptivePriorityScheduling(processes);
-
-        // Assert
-        assertEquals(expectedGanttChart, actualGanttChart);
+    static Stream<Arguments> provideProcessesAndExpectedSchedules() {
+        return Stream.of(Arguments.of(List.of(new ProcessDetails("P1", 0, 5, 2), new ProcessDetails("P2", 1, 4, 4), new ProcessDetails("P3", 2, 2, 6), new ProcessDetails("P4", 4, 1, 8)), List.of("P1", "P2", "P3", "P3", "P4", "P2", "P2", "P2", "P1", "P1", "P1", "P1")),
+            Arguments.of(List.of(new ProcessDetails("P1", 2, 5, 3), new ProcessDetails("P2", 5, 3, 5), new ProcessDetails("P3", 7, 1, 9)), List.of("Idle", "Idle", "P1", "P1", "P1", "P2", "P2", "P3", "P2", "P1", "P1")));
     }
 }