Unexpected Java performance - java

I have just thrown everything I know about Java optimisation out the window. I have the following task:
Given a 2D array representing a playing field and a position on the field, fill another array with the number of steps a player can make to get to every other position in the field. The player can move up, down, left and right. For example, the first neighbours will be all 1's, with the diagonals being all 2's.
For the first attempt, I tried a simple 4-way floodfill algorithm. It wad dreadfully slow.
Secondly, I decided to get rid of the recursion and use a simple Queue. It worked lovely and gave a huge speed-up (very roughly 20x). Here is the code:
private void fillCounterArray(int[] counters, int position) {
Queue<Integer> queue = new ArrayDeque<Integer>(900);
// Obtain the possible destinations from position, check the valid ones
// and add it the stack.
int[] destination = board.getPossibleDestinations(position);
for (int i = 0; i < destination.length; i++) {
if (board.getBoard()[destination[i]] == Board.CLEAR) {
counters[destination[i]] = 1;
queue.add(destination[i]);
}
}
// Now fill up the space.
while (!queue.isEmpty()) {
int pos = queue.remove();
int steps = counters[pos];
destination = board.getPossibleDestinations(pos);
for (int i = 0; i < destination.length; i++) {
int dest = destination[i];
if (board.getBoard()[dest] == Board.CLEAR && (counters[dest] > steps + 1 || counters[dest] == 0)) {
counters[dest] = steps + 1;
queue.add(dest);
}
}
}
}
Now, "common-sense" told me that the queue operations with a static array and an int-pointer would be faster. So I removed the Queue and use a standard int[] array. The code is identical, except for the queue-like operations. It now looks like this (As you can see, I use to live by the C-side :)):
private void fillCounterArray(int[] counters, int position) {
// Array and its pointer.
int[] queue = new int[900]; // max size of field
int head = 0;
// Obtain the possible destinations from position, check the valid ones
// and add it the stack.
int[] destination = board.getPossibleDestinations(position);
for (int i = 0; i < destination.length; i++) {
if (board.getBoard()[destination[i]] == Board.CLEAR) {
counters[destination[i]] = 1;
queue[head++] = dest[i];
}
}
// Now fill up the space.
while (head > 0) {
int pos = queue[--head];
int steps = counters[pos];
destination = board.getPossibleDestinations(pos);
for (int i = 0; i < destination.length; i++) {
int dest = destination[i];
if (board.getBoard()[dest] == Board.CLEAR && (counters[dest] > steps + 1 || counters[dest] == 0)) {
counters[dest] = steps + 1;
queue[head++] = dest;
}
}
}
}
When I ran this "optimised code" it was significantly slower than using the Queue and only about twice as fast as the recursive technique. There is also hardly any difference when I declare the array as an instance variable. How is this possible?

Your reversed the order while optimising I think;
The queue is fifo, first in first out
The array is lifo, last in first out, as you walk it downwards
That will usually give you different performance ;-)

Insert two Counters in each Loop one in the for loop and one in the while loop in both versions, compare the numbers you get at the end, how many rounds do you make in each version, if you have another Loop in getPossibleDestination then log the pos variable too.
I guess that would be a good starting point to figure it out.
Another way would be to print the time difference on different lines in your program, let say before the 1st loop, between both and at the end, once you compare results and know where it takes a long time in the second Version you can print timestamps in the loop on different lines.

Related

How to get index in Java array that defines start and end of available space

So I tried searching for how to solve this issue I'm having. I need some sort of way in Java to go through an array and find slots (indexes) where it's empty (zeros) so for example I have this array:
int[] arr = {1,1,0,0,0,0,0,1,0,0};
So I want to for example get out two values from here. If my objSize (see below) is 4. I want to get the array index of 2 and 6 since the size of objSize will fit there. These indexes specify space between that is available. I can't really seem to figure this out.
for (int x = 0; x < matrix.length; x++) {
if (arr[x] == 0) {
start = col;
if (start == objSize) {
stop = col;
}
} else {
start = 0;
}
}
How can I do this? I've made an attempt that doesn't work for obvious reasons.
Well, first off I don't really understand your intentions behind the code you already submitted, so it is hard to just improve on it. Instead, I am going to walk you through a similar solution, which is the following.
int objsize = 4;
int[] arr = {1,1,0,0,0,0,0,1,0,0};
int start = 0;
int stop = 0;
for(int i = 0; i < arr.length - 1; i++) {
if(arr[i] != 0){
start = i;
stop = i;
continue;
} else {
stop++;
if(stop-start >= objsize) {
break;
}
}
}
When looking for a sequence in an array, that matches a given condition (in your case 4 consecutive 0 values) you should have two "pointers" for your start and stop value, where the stop value could be the i/the current array pointer as well.
Then you go sequentially through your array and have two general cases:
The value at your current index doesn't match your condition of being 0, so you reset your start and stop pointer to the current position in the array and continue.
Your current index matches the condition. In this case, you leave the starting pointer where it last didn't match the condition and move your stop-pointer forward. If then your finishing criteria of 4 consecutive 0 values is matched, you can leave the for loop over the array.
In the code provided above, the returned/final start and stop value are:
start: exclusively indexed
stop: inclusively indexed.
You said you expected the values returned to be 2 and 6, as this would be the longest concurrent series of 0 values. But as the criteria of 4 consecutive values is already matched at 2 and 5, the code above delivers those values, but can easily be adopted to return the full consecutive sequence.
to go through an array and find slots (indexes) where it's empty (zeros)
In order to find all the slots in the given array, you need a container to store them. A plain array isn't applicable here, because you have to provide the length and it's not possible to know how many slots there are in the given array. For that purpose, we can use ArrayList which utilizes array under the hood and grows gradually while elements are being added into it.
And because each slot is comprised of two values we need an object that encapsulates them. There are two options here: it could be easier a class or record (available since Java 16). And it will look like that:
public record Slot(int start, int end) {
public int getSize() {
return end - start;
}
}
The class below is absolutely identical in terms of functionality. Constructor, getters, equals(), hashCode(), toString() are provided to a record implicitly, but if your choice is class then you have to declare them yourself). Meanwhile with record you need to declare only a custom method getSize().
public class Slot {
private final int start;
private final int end;
public Slot(int start, int end) {
this.start = start;
this.end = end;
}
public int getSize() {
return end - start;
}
// getters, equals(), hashCode(), toString()
}
To implement this algorithm only one local variable start is needed. It's convenient to initialize it will -1 because this illegal position in the array. Therefore it's easy to distinguish the default value of start and beginning of a slot.
The end of the slot will be the first occurrence of the 1 when start != -1. When the end is found a new instance of the Slot is being created and added to the list.
The case when the given array contains a slot at the end must be treated separately after the loop.
A ternary operator start == -1 ? x : start; that is used to update the value of start is an equivalent of if (start == -1) start = x;.
public static void main(String[] args) {
int[] arr = {1,1,0,0,0,0,0,1,0,0};
List<Slot> slots = new ArrayList<>();
int start = -1;
for (int x = 0; x < arr.length; x++) {
if (arr[x] == 0) {
start = start == -1 ? x : start;
} else if(start != -1) {
slots.add(new Slot(start, x));
start = -1;
}
}
// adding the last slot at the end of array
if(start != -1) {
slots.add(new Slot(start, arr.length));
}
System.out.println("All slots: " + slots); // all slots that are found
System.out.println("Slots of size 2: " + getSlotOfSize(slots, 2));
System.out.println("Slots of size 5: " + getSlotOfSize(slots, 5));
}
This method is used to filter out slots of a particular size:
public static List<Slot> getSlotOfSize(List<Slot> slots, int size) {
List<Slot> result = new ArrayList<>(); // a new list to preserve the slots list intact
for (Slot slot: slots) {
if (slot.getSize() == size)
result.add(slot);
}
return result;
}
Output (starting index inclusive, ending index exclusive)
All slots: [Slot[start=2, end=7], Slot[start=8, end=10]]
Slots of size 2: [Slot[start=8, end=10]]
Slots of size 5: [Slot[start=2, end=7]]

How to return all array permutations iteratively into a two-dimensional array?

I am trying to write a program that will iterate through all possible permutations of a String array, and return a two dimensional array with all the permutations. Specifically, I am trying to use a String array of length 4 to return a 2D array with 24 rows and 4 columns.
I have only found ways to print the Strings iteratively but not use them in an array. I have also found recursive ways of doing it, but they do not work, as I am using this code with others, and the recursive function is much more difficult.
For what I want the code to do, I know the header should be:
public class Permutation
{
public String[][] arrayPermutation(String[] str)
{
//code to return 2D array
}
}
//I tried using a recursive method with heap's algorithm, but it is very //complex with its parameters.
I am very new to programming and any help would be greatly appreciated.
Your permutation-problem is basically just an index-permutation problem.
If you can order the numbers from 0 to n - 1 in all possible variations, you can use them as indexes of your input array, and simply copy the Strings. The following algorithm is not optimal, but it is graphic enough to explain and implement iteratively.
public static String[][] getAllPermutations(String[] str) {
LinkedList<Integer> current = new LinkedList<>();
LinkedList<Integer[]> permutations = new LinkedList<>();
int length = str.length;
current.add(-1);
while (!current.isEmpty()) {
// increment from the last position.
int position = Integer.MAX_VALUE;
position = getNextUnused(current, current.pop() + 1);
while (position >= length && !current.isEmpty()) {
position = getNextUnused(current, current.pop() + 1);
}
if (position < length) {
current.push(position);
} else {
break;
}
// fill with all available indexes.
while (current.size() < length) {
// find first unused index.
int unused = getNextUnused(current, 0);
current.push(unused);
}
// record result row.
permutations.add(current.toArray(new Integer[0]));
}
// select the right String, based on the index-permutation done before.
int numPermutations = permutations.size();
String[][] result = new String[numPermutations][length];
for (int i = 0; i < numPermutations; ++i) {
Integer[] indexes = permutations.get(i);
String[] row = new String[length];
for (int d = 0; d < length; ++d) {
row[d] = str[indexes[d]];
}
result[i] = row;
}
return result;
}
public static int getNextUnused(LinkedList<Integer> used, Integer current) {
int unused = current != null ? current : 0;
while (used.contains(unused)) {
++unused;
}
return unused;
}
The getAllPermutations-method is organized in an initialization part, a loop collecting all permutations (numeric), and finally a convertion of the found index-permutation into the String-permutations.
As the convertion from int to String is trivial, I'll just explain the collection part. The loop iterates as long, as the representation is not completely depleted, or terminated from within.
First, we increment the representation (current). For that, we take the last 'digit' and increment it to the next free value. Then we pop, if we are above length, and look at the next digit (and increment it). We continue this, until we hit a legal value (one below length).
After that, we fill the remainder of the digits with all still remaining digits. That done, we store the current representation to the list of arrays.
This algorithm is not optimal in terms of runtime! Heap is faster. But implementing Heap's iteratively requires a non-trivial stack which is tiresome to implement/explain.

Reducing the time of execution of the following code [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
I am working on a problem. Out of 17 test cases 10 works fine and gives the result in less than a second but in 7 cases it is taking 2 seconds which are beyond the time limit. Following is the code
import java.util.*;
import java.io.*;
class TestClass
{
static PrintWriter wr = new PrintWriter(System.out);
public static void func1(int arr[], int n)
{
int temp = arr[0];
for (int jj = 0; jj < n; jj++)
{
if (jj == (n - 1))
arr[jj] = temp;
else
arr[jj] = arr[jj + 1];
}
}
public static void func2(int arr[], int n, int rt)
{
int count = 0;
for (int a = 0; a < n; a++)
{
for (int b = a; b < n; b++)
{
if (arr[a] > arr[b])
count++;
}
}
if (rt == (n - 1))
wr.print(count);
else
wr.print(count + " ");
}
public static void main(String args[]) throws Exception
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine().trim();
StringTokenizer st = new StringTokenizer(str);
int t = Integer.parseInt(st.nextToken());
for (int i = 0; i < t; i++) //for test cases
{
str = br.readLine().trim();
st = new StringTokenizer(str);
int n = Integer.parseInt(st.nextToken());
int arr[] = new int[n];
str = br.readLine().trim();
st = new StringTokenizer(str);
for (int j = 0; j < n; j++) //to take input of array for each test case
{
arr[j] = Integer.parseInt(st.nextToken());
}
for (int rt = 0; rt < n; rt++) //for number of times circular shifting of array is done
{
func1(arr, n); //circularly shifts the array by one position
func2(arr, n, rt); //prints the number of inversion counts
}
if (i != (t - 1))
wr.println();
}
wr.close();
br.close();
}
}
Can someone suggest how to optimize the code so that it takes less time in execution.
I know BufferReader and PrintWriter takes less time as compared to Scanner and System.out.print. I was using scanner and System.out.print earlier but changed it later in hope of getting less time but it didn't help. Also I did it earlier without the use of func1 and func2 and did all the operations in main only. The time in both the cases remains the same.
I am getting the currect output in all the cases so code is correct, I just need help in optimizing it.
The website you are using acquires questions from past programming competitions. I recognize this as a familiar problem
Like most optimization questions, the preferred steps are:
Do less.
Do the same in fewer instructions.
Don't use functions.
Use faster instructions.
In your case, you have an array, and you wish to rotate it a number of times, and then to process it from the rotated position.
Rotating an array is an incredibly expensive operation, because you typically need to copy every element in the array into a new location. What is worse for you is that you are doing it the simplest way, you are rotating the array one step for every step needing rotation.
So, if you have a 100 element array that needs rotated 45 steps, you would then have (3 copies per element swap) 100 * 45 * 3 copies to perform your rotation.
In the above example, a better approach would be to figure out a routine that rotates an array 45 elements at a time. There are a number of ways to do this. The easiest is to double the RAM requirements and just have two arrays
b[x] = a[(mod(x+45), a.length)]
An even faster "do less" would be to never rotate the array, but to perform the calculation in reverse. This is conceptually the function of the desired index in the rotated array to the actual index in the pre-rotated array. This avoids all copying, and the index numbers (by virtue of being heavily manipulated in the math processing unit) will already be stored in the CPU registers, which is the fastest RAM a computer has.
Note that once you have the starting index in the original array, you can then calculate the next index without going through the calculation again.
I might have read this problem a bit wrong; because, it is not written to highlight the problem being solved. However, the core principles above apply, and it will be up to you to apply them to the exact specifics of your programming challenge.
An example of a faster rotate that does less
public static void func1(int arr[], int shift) {
int offset = shift % arr.length;
int [] rotated = new int[arr.length];
// (arr.length - 1) is the last index, walk up till we need to copy from the head of arr
for (int index = 0; index < (arr.length - 1) - offset; index++) {
rotated[index] = arr[index+offset];
}
// copy the end of the array back into the beginning
for ( int index = (arr.length - 1) - offset; index < arr.length; index++ ) {
rotated[index] = (offset - ((arr.length - 1) - index) - 1);
}
System.arraycopy(rotated, 0, arr, 0, arr.length);
}
This copies the array into its rotated position in one pass, instead of doing a pass per index to be rotated.
The first rule of optimisation (having decided it is necessary) is to use a profiler. This counts how many times methods are invoked, and measures the accumulated time within each method, and gives you a report.
It doesn't matter if a method is slow if you only run it a few times. If you run it hundreds of thousands of times, you need to either make it faster, or run it fewer times.
If you're using a mainstream IDE, you already have a profiler. Read its documentation and use it.
The other first rule of optimisation is, if there's already literature about the problem you're trying to solve, read it. Most of us might have invented bubble-sort independently. Fewer of us would have come up with QuickSort, but it's a better solution.
It looks as if you're counting inversions in the array. Your implementation is about as efficient as you can get, given that naive approach.
for(int i=0; i< array.length; i++) {
int n1 = array[i];
for(int j=i+1; j< array.length; j++) {
n2 = array[j];
if(n1 > n2) {
count++;
}
}
}
For an array of length l this will take ( l - 1) + ( l - 2 ) ... 1 -- that's a triangular number, and grows proportionally to the square of l.
So for l=1000 you're doing ~500,000 comparisons. Then since you're repeating the count for all 1000 rotations of the array, that would be 500,000,000 comparisons, which is definitely the sort of number where things start taking a noticeable amount of time.
Googling for inversion count reveals a more sophisticated approach, which is to perform a merge sort, counting inversions as they are encountered.
Otherwise, we need to look for opportunities for huge numbers of loop iterations. A loop inside a loop makes for big numbers. A loop inside a loop inside another loop makes for even bigger numbers.
You have:
for (int i = 0; i < t; i++) {
// stuff removed
for (int rt = 0; rt < n; rt++) {
// snip
func2(arr, n, rt); //prints the number of inversion counts
}
// snip
}
public static void func2(int arr[], int n, int rt) {
// snip
for (int a = 0; a < n; a++) {
for (int b = a; b < n; b++) {
// stuff
}
}
// snip
}
That's four levels of looping. Look at the input values for your slow tests, and work out what n * n * n * t is -- that an indicator of how many times it'll do the work in the inner block.
We don't know what your algorithm is supposed to achieve. But think about whether you're doing the same thing twice in any of these loops.
It looks as if func1() is supposed to rotate an array. Have a look at System.arrayCopy() for moving whole chunks of array at a time. Most CPUs will do this in a single operation.

Trying to apply Knuth's Mastermind algorithm to my Mastermind project in Java

I've been trying to implement Knuth's algorithm to my version of Mastermind, and I got a bit stuck on step 6 of the algorithm. Here is a link to the steps I'm using. (Scroll down a bit)
And here's step 6 copypasted from the link:
6 Apply minimax technique to find a next guess as follows: For each
possible guess, that is, any unused code of the 1296 not just those in
S, calculate how many possibilities in S would be eliminated for each
possible colored/white peg score. The score of a guess is the minimum
number of possibilities it might eliminate from S. From the set of
guesses with the maximum score, select one as the next guess, choosing
a member of S whenever possible. (Knuth follows the convention of
choosing the guess with the least numeric value e.g. 2345 is lower
than 3456. Knuth also gives an example showing that in some cases no
member of S will be among the highest scoring guesses and thus the
guess cannot win on the next turn, yet will be necessary to assure a
win in five.)
Anyway, whenever I'm trying to perform step 6, somewhere in my code a problem seems to occur. The array of possible combinations keeps getting smaller (upwards to 8 on turn 9 on which it shuts down), but it's no where near as efficient as it should be, because this algorithm should guess the code correctly after 5 turns. I've been looking around and checking the other Knuth algorithm questions on Stackoverflow but I couldn't find my answer in those, so I hoped I could maybe get some more direct help. What I'd basically like to know is where my code is malfunctioning, why, and how to fix it. Any answer will be much appreciated!
This is the code I'm using to generate the next (or first) code that the computer will guess.
In this code, possibleCombList functions as my version of 'S' as described in the steps, and code functions as my current/next guess.
public void generateCode() {
ArrayList<String> bestGuesses = new ArrayList<String>(); // Create new
// array in
// which I
// store all
// the best
// guesses.
if (totalGuesses == 0) { // If this is the first guess, pick spot 1122
// from the array of combinations as my next
// code.
code = possibleCombList.get(1122);
}
else if (possibleCombList.size() == 1) { // If there's only one
// combination left in the
// array, pick that one.
code = possibleCombList.get(0);
}
else { // If none of the above are true, do this;
int tempBlackPins = 0;
int tempWhitePins = 0;
possibleCombList.remove(possibleCombList.indexOf(code)); // Remove
// last
// guess.
for (int i = 0; i < possibleCombList.size(); i++) { // (Step 5)
// Delete any
// code that
// would not
// give the same
// response if
// the last
// guess were
// the code.
for (int a = 0; a < 4; a++) {
if (possibleCombList.get(i).charAt(a) == (code.charAt(a))) {
tempBlackPins++;
} else if (possibleCombList.get(i).contains("" + code.charAt(a))) {
tempWhitePins++;
}
}
if (tempBlackPins != blackPins && tempWhitePins != whitePins) {
possibleCombList.remove(i);
}
}
int maxMinimum = 0;
for (int j = 0; j < possibleCombList.size(); j++) { // (Step 6)
// Apply minMax
// technique
// (calculate
// which codes
// would
// eliminate the
// most
// possibilities
// next turn and
// pick one of
// those codes).
int minimum = Integer.MAX_VALUE;
tempBlackPins = 0;
tempWhitePins = 0;
for (int i = 0; i < possibleCombList.size(); i++) {
for (int a = 0; a < 4; a++) {
if (possibleCombList.get(i).charAt(a) == (code.charAt(a))) {
tempBlackPins++;
} else if (possibleCombList.get(i).contains("" + code.charAt(a))) {
tempWhitePins++;
}
}
if (tempBlackPins != blackPins && tempWhitePins != whitePins) {
minimum++;
}
}
if (minimum == maxMinimum && minimum > 0) {
bestGuesses.add(possibleCombList.get(j));
}
if (minimum > maxMinimum) {
maxMinimum = minimum;
bestGuesses.clear();
bestGuesses.add(possibleCombList.get(j));
}
}
System.out.println(bestGuesses.size());
code = bestGuesses.get(0); // Grab position 0 of the array with best
// guesses and make that the next guess.
}
}
Thank you guys for helping me out!
There is something wrong with the way you correct your guess.
Consider this case:
Code: (Red -x - x -x)
Guess: (x - Red - Red - x)
In your evaluation you will get two white pins while it should be only one.

Print first 20 items in array in reverse, then print the next 20 in reverse, and so on

so I'm working on my Java assignment where I'm given a big array.
I'm told to print the first 20 items in the array in reverse order,
then print the next 20 items in reverse order again, and so forth until I reach the end of the array.
I was able to work out how to print the first items in reverse, but then I'm having trouble implementing something that would let me continue where I left from the original array.
I'm also only allowed to have 21 items stored at a time.
Here's what I have so far (50items instead of 20)
public static void doIt(BufferedReader r, PrintWriter w) throws IOException {
LinkedList<String> s = new LinkedList<String>();
int counter = 0;
int max = 50;
for (String line = r.readLine(); line != null; line = r.readLine()) {
if (counter < max) {
s.addFirst(line);
counter++;
}
if (counter == max) {
for (String n : s) {
System.out.println(n);
}
}
}
}
I was wondering if someone can help me out, not sure what I can do from here.
First, you need to print the list whenever counter hits a multiple of 20 as well as when it hits max. Then, after you print the contents of s, clear the list:
s.clear();
That will remove all elements so it will fill up again. You also need to print the list after the for loop exits, otherwise the last few items will be left unprinted.
Note that you are not using an array anywhere in this code. It's not clear that you are following the spirit of the assignment by using a LinkedList. But only you know what the rubric is.
I hope this can get you started:
void example() {
for (int i = 0; i < 50; i++) { //fill array to be read (for this example)
myArray[i] = i;
}
readback();
}
void readback() {
int batch = 1; //represents a portion of the read operation
int batchSize = 20; //the size of the read portion
int pos = 0; //the current index of the array while it is being read
int hi; //the top of the batch
int lo; //the bottom of the batch
while (pos < myArray.length) {
if (batch*batchSize<myArray.length) { //make sure you are not going over the array boundary
hi = batch*batchSize;
lo = hi - batchSize;
} else {
hi = myArray.length;
lo = pos;
}
for (int i = hi - 1; i >= lo; i--) { //read
System.out.println(myArray[i]);
pos++;
}
batch++; //go to the next batch
}
}
For this part of the question:
I'm told to print the first 20 items in the array in reverse order, then print the next 20 items in reverse order again, and so forth until I reach the end of the array.
One simple solution would be to:
iterate 20 places in the array
store this position in a temp index
iterate back 20 places printing the array
repeat process from stored temp index
Also, keep in mind if the last print might have less than 20 elements.
int size = 20; // size of reversed chunks
for(int i = 0; i < array.length; i += size) {
int j = (i + (size - 1) < array.length) ? (i + size - 1) : array.length - 1;
for(; j >= i; j--) {
System.out.print(array[j] + " ");
}
}
However, there is no array in your code so I am not sure what you meant by that. You are reading values from a file and then using a LinkedList to print them in reverse. A better, more natural data structure, for printing in reverse (as well as most "reversal" operations) would be a Stack although Java's implementation for LinkedList is implemented such that it allows for Stack (LIFO) behavior. It is just generally used as a Queue (FIFO) structure. My answer will use a LinkedList as well to make it consistent with your approach but think about a Stack in this situation in the future.
So, since you are reading numbers, line by line from a file, here is what you can do:
You can read and insert the numbers at the top of a LinkedList until you reach the max value or the end of file
You already have that part working
Print all the numbers by removing them from the top of the LinkedList which will make them in reverse order
You are printing them but not removing them or clearing the list by calling s.clear()
Once you reach the end of file you could end up with values still in the LinkedList because you reached end of file before you reached max items and the loop finished but nothing was printed. Print these values as well.
Another thing, it seems like you are not writing to the file so you don't need the PrintWriter parameter of the function.
Here is the code:
public static void doIt(BufferedReader r) throws IOException {
LinkedList<String> s = new LinkedList<String>();
int counter = 0;
int max = 50;
for (String line = r.readLine(); line != null; line = r.readLine()) {
if (counter < max) {
s.addFirst(line);
counter++;
}
if (counter == max) {
while(!s.isEmpty()) { // remove and print in reverse order
System.out.println(s.removeFirst());
}
counter = 0; // reset counter
}
}
// print the remaining elements, if they exist
while(!s.isEmpty()) { // remove and print in reverse order
System.out.println(s.removeFirst());
}
}

Categories

Resources