LinkedList of File IO appears the same through output - java

The LinkedList only shows the same output. I am trying to use the last while loop but it does not work. This is a "Duck Duck Goose" problem. I am not supposed to use Indexing.
19 names
http://collabedit.com/q248e
public class DuckDuckGoose {
public static void main(String[] args) {
LinkedList<String> linkedlist = new LinkedList<String>();
// add try catch to add list
try {
FileReader fr = new FileReader(...players.txt");
Scanner inFile = new Scanner(fr);
while (inFile.hasNextLine()) {
linkedlist.add(inFile.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Iterator<String> iterator = linkedlist.iterator();
// checks until the last list
while (!iterator.hasNext()) {
if (iterator.next().equals(getRandomBoolean())) {
iterator.remove();
}
}
System.out.println(linkedlist);
}
public static boolean getRandomBoolean() {
return Math.random() < 10 * 0.5;
}
}

if (iterator.next().equals(getRandomBoolean())) {
This is never true, because the iterator contains Strings, not Booleans, so you never execute the iterator.remove();.
Instead:
iterator.next(); // gets but ignores the next String.
if (getRandomBoolean()) {
Additionally, your loop never executes:
while (!iterator.hasNext()) {
because the iterator initially has a next element.
Remove the !.
Additionally, this:
Math.random() < 10 * 0.5
Is always true, because Math.random() is strictly less than 1, and 10 * 0.5 is 5.
Drop the 10 *, or pick a value on the RHS of the < which is between 0 and 1.

Related

Weird Java Concurrent modification exception example [duplicate]

This question already has answers here:
Why am I not getting a java.util.ConcurrentModificationException in this example?
(10 answers)
Closed 4 years ago.
If we write like this, there is a concurrent modification exception :
public static void main(String... args) {
List<String> listOfBooks = new ArrayList<>();
listOfBooks.add("Programming Pearls");
listOfBooks.add("Clean Code");
listOfBooks.add("Effective Java");
listOfBooks.add("Code Complete");
System.err.println("Before deleting : " + listOfBooks);
for (String book : listOfBooks) {
if (book.contains("Code")) {
listOfBooks.remove(book);
}
}
System.err.println("After deleting : " + listOfBooks);
}
On the other hand, if we write like this, there is NO concurrent modification exception !
Notice that code is exact the same, except the strings for compare, in first example it is a Code, and in second it is a Java
public static void main(String... args) {
List<String> listOfBooks = new ArrayList<>();
listOfBooks.add("Programming Pearls");
listOfBooks.add("Clean Code");
listOfBooks.add("Effective Java");
listOfBooks.add("Code Complete");
System.err.println("Before deleting : " + listOfBooks);
for (String book : listOfBooks) {
if (book.contains("Java")) {
listOfBooks.remove(book);
}
}
System.err.println("After deleting : " + listOfBooks);
}
I'm using Netbeans 8.2, Windows 7 32bit, with JDK 1.8.0_131
What's wrong ?
List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.
Quoting from this Java Bug (JDK-4902078) .
When the Collections Framework was added to the platform it was deemed too expensive to check for comodification once rather than twice per iteration; the check was made on Iterator.next rather than Iterator.hasNext. Expert reviewers thought this was sufficient. They were unaware that it fails to detect one important case: if an element is removed from the list immediately prior to the final call to hasNext in an iteration, the call returns false and the iteration terminates, silently ignoring the last element on the list.
You can also check this answer :-
https://stackoverflow.com/a/8189786/1992276
There are two ways used to iterate over an collection: enumeration and iterator.
First one allows for the collection to be modified during iteration (fail slow), second does not (fail fast). In a for-each loop you are using an iterator, so any modification to the collection, during it's iteration would cause an exception.
You have 3 choices, to solve this problem:
Use an iterator instead:
Iterator<String> bookIt = listOfBooks.iterator();
while(bookIt.hasNext()){
String book = bookIt.next();
if (book.contains("Java")) {
bookIt.remove();
}
}
Create a new list with only acceptable elements (filter out the unwanted):
List<String> booksWithNoCode = listOfBooks.stream()
.filter(book-> !book.contains("Code"))
.collect(toList())
Use Collection.removeIf(), you will remove all elements from the list, that are matching given criteria.
listOfBooks.removeIf(book-> book.contains("Code"))
You can find more information in this post and here.
You can't modify the listOfBooks while you are iterating though it with the for each loop.
edit:
for (String book : listOfBooks) {
if (book.contains("Code")) {
listOfBooks.remove(book);
}
}
Is the same as:
for (Iterator<String> i = listOfBooks.iterator(); i.hasNext();) {
String book = i.next();
if (book.contains("Code")) {
listOfBooks.remove(book);
}
}
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java
The key in the arraylist code is:
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
and the iterator code:
public boolean hasNext() {
return cursor != size;
}
#SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
The cursor always points to the next element so when you get the "Effective Java" i = 2 but cursor is 3.
When you call the remove the cursor is at 3 and the size is 4.
The size is then decremented by the remove and now cursor == size and the next hasNext() returns false ending the loop.

why cant my function keep a total amount of int values within file?

I am making a program that reads a file of mixed values (int and string), prints only the integer values and keeps a running total of the amount of integer values within the file. Everything is working except for my running total of integer values within a given file and i am very confused on why it keeps printing 0 when i know there are more then 0 integer values within the file.
Here is my code:
package davi0030_a03;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class MyFile {
private String fileName; // name of the file
private int count = 0; // number of valid integers in the file
private final int MAX_SIZE = 10; // the size of the array
private Scanner inputStream = null;
private int[] theArray = new int[MAX_SIZE];
private boolean strangeInt = false;
private int total = 0;
// constructor to set the file name
public MyFile(String theName) { // constructor to set the file name
this.fileName = new String(theName);
// you may or may not want to do other stuffs here
}
public void openFile() {
System.out.println("opening file: " + fileName);
try {
inputStream = new Scanner(new FileInputStream("src/davi0030_a03/"
+ fileName));
} catch (FileNotFoundException e) {
System.out.println("File was not found or could not be opened");
}
}
// log a message on whether two ints in the file add to target
public void findPair(int target) {
openFile();
fileToArray();
findStrangeInt();
findTotal();
}
public void findTotal(){
inputStream.reset();
while(inputStream.hasNext()){
if(inputStream.hasNextInt()){
total +=1;
}
inputStream.next();
}
System.out.println(total);
}
public void findStrangeInt() {
inputStream.reset();
while (inputStream.hasNext()) {
try {
Integer.parseInt(inputStream.next());
} catch (NumberFormatException nfe) {
strangeInt = true;
}
}
if (strangeInt = true) {
System.out.println("File contains an incorrectly written int");
}
}
public void fileToArray() {
inputStream.reset();
while (inputStream.hasNext() && count < MAX_SIZE) {
if (inputStream.hasNextInt()) {
theArray[count] = inputStream.nextInt();
count++;
}
}
}
// print the content of the file
public void printFile() {
openFile();
inputStream.reset();
System.out.println("Printing content of file " + fileName);
while (inputStream.hasNext()) {
try {
int convert = Integer.parseInt(inputStream.next());
System.out.println(convert);
} catch (NumberFormatException nfe) {
System.out.println("xxx");
}
}
}
}
content of file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
a
b
d
EDIT: My solution below most likely solves the logic issue regarding your searching the file. However, I suggest you read some of the other comments the question has gotten. The IO handling here especially needs some improvement.
I believe your issue lies in your while statement. According to java documentation on the Scanner class,here, the method .hasNextInt() is returning based on the next element scanned. I think you are assuming it will return true as long as there are ints in the file. This is not the case. If the first thing the scanner hits is not an int, it is returning false and exiting your while loop. This would explain the returned 0, the value you initialize your variable 'total' to. I would suggest you do something like the following:
while(scanner.hasNext()){
if(scanner.hasNextInt()){
total +=1;
}
scanner.next();
}

Changing values of static class variables in a nested loop

I'm having an issue with changing the values of a class variable within nested loops - I can't figure out why. I'm guessing it's because the variable is static. But it's a static method and because it's used for listing a User in a system from a file, it has to be static (I'm calling it from main method to read file to TreeMaps). Is it not possible to rewrite a static class variable from within a method? If it's possible - what the heck am I doing wrong?
public class Loan{
protected int noOfLoans;
protected int noOfReturns;
protected User user=new User();
protected static Book book= new Book();
protected Map <Integer, Book> currentLoans=new TreeMap <Integer, Book>();
protected Map <Integer, Book> returned=new TreeMap <Integer, Book>();
protected static Map<Integer, Loan> loanList=new TreeMap<Integer, Loan>();
public static void main(String[] args){
readLoans();
}
public static void readLoans(){
loanList.clear();
BufferedReader reader = null;
try {
reader=new BufferedReader(new FileReader("loans.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String line = null;
try {
line = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
while (line!=null) {
String[] splitOut=line.split("-");
String[] loan_User=splitOut[0].split(",");
String[] loan_CurrentLoans=splitOut[2].split(",");
String[] loan_Returned=splitOut[4].split(",");
Loan loan = new Loan();
loan.user.setFirstName(loan_User[0]);
loan.user.setSurname(loan_User[1]);
loan.user.setPersonalID(loan_User[2]);
for (int i = 1; i <= Integer.parseInt(splitOut[1]); i++) {
book.setName(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)]);
book.setAuthorFirstname(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)+1]);
book.setAuthorSurname(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)+2]);
book.setISBN(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)+3]);
loan.currentLoans.put(i, book);
}
for (int i = 1; i <= Integer.parseInt(splitOut[3]); i++) {
book.setName(loan_Returned[((Integer.parseInt
(splitOut[3])-1)*4)]);
book.setAuthorFirstname(loan_Returned[((Integer.parseInt
(splitOut[3])-1)*4)+1]);
book.setAuthorSurname(loan_Returned[((Integer.parseInt
(splitOut[3])-1)*4)+2]);
book.setISBN(loan_Returned[((Integer.parseInt
(splitOut[3])-1)*4)+3]);
loan.returned.put(i, book);
}
loan.setNoOfLoans(Integer.parseInt(splitOut[1]));
loan.setNoOfReturns(Integer.parseInt(splitOut[3]));
loanList.put(loanList.size()+1, loan);
try {
line=reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here's an input line for reference:
John,Doe,8012311213-2-a book,Author,Authorson,1234567890123,another book,Author,Authorson,2345678901234-1-a returned book,Author,Authorson,3456789012345
What I'm hoping to get when printing above line:
Current Loans:
1. a book by Author Authorson (1234567890123)
2. another book by Author Authorson (2345678901234)
Returned Loans:
1. a returned book by Author Authorson (3456789012345)
What I'm currently getting:
Current Loans:
1. a book by Author Authorson (1234567890123)
2. a book by Author Authorson (1234567890123)
Returned Loans:
1. a book by Author Authorson (1234567890123)
And
readLoans();
System.out.println(loanList.get(2).currentLoans.get(1).toString());
System.out.println(loanList.get(2).currentLoans.get(2).toString());
returns
a returned book by Author Authorson (3456789012345)
a returned book by Author Authorson (3456789012345)
Which leads me to believe I actually cannot make instances of my static Book object, but have to make it non-static and try to create instances of the object within the method. If so - how do I do that?
From here, it's hard to understand how you can understand as much as you do, and yet be so confused, at the same time. I don't mean that to be insulting - just to say that I'm not at all sure I understand where you are.
Create instances by using new. So in your two loops, where you keep overwriting the one static book, instead you need a local variable that you assign a new book to and then set the fields on.
The problem isn't that your Book is static, the problem is more simply that it's the same object every time you change it during the loop. This does happen because you've declared it as a static field but you are on the wrong track thinking the way you are about it.
Let's simplify the problem and instead of a Book, use this to illustrate:
class AnObject {
int aValue;
}
And instead of IO, just loop some times and add it to a list:
class PersistenceOfChangesDemo {
static List<AnObject> theList = new ArrayList<AnObject>();
public static void main(String[] args) {
AnObject theObject = new AnObject();
for(int i = 1; i <= 3; i++) {
/* reassign the object's value */
theObject.aValue = i;
/* adds the same object each time */
theList.add(theObject);
}
/* theList is now of size 3
* but all its elements refer to the same object (theObject) */
for(AnObject anObject : theList) {
/* prints '3' every time
* because that was the last value assigned */
System.out.println(anObject.aValue);
/* prints 'true' every time */
System.out.println(anObject == theObject);
}
}
}
The solution is that you need to create a new object each time you want a new one:
class PersistenceOfChangesDemo {
static List<AnObject> theList = new ArrayList<AnObject>();
public static void main(String[] args) {
for(int i = 1; i <= 3; i++) {
/* make a new object each time */
AnObject anObject = new AnObject();
anObject.aValue = i;
theList.add(anObject);
}
/* theList now has references to 3 different objects */
for(AnObject anObject : theList) {
/* prints 1, 2, 3 */
System.out.println(anObject.aValue);
}
}
}
Per your comment, make sure you are creating the new instance for each time you put it in to the map:
for (int i = 1; i <= Integer.parseInt(splitOut[1]); i++) {
Book newBook = new Book();
newBook.setName(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)]);
newBook.setAuthorFirstname(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)+1]);
newBook.setAuthorSurname(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)+2]);
newBook.setISBN(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)+3]);
loan.currentLoans.put(i, newBook);
}
it's just Reference problem. All three are referring to same object static book so represent the same details which are inserted last.
The change is only create new object of Book() instead of using same object for different detail.
try below code
Loan loan = new Loan();
loan.user.setFirstName(loan_User[0]);
loan.user.setSurname(loan_User[1]);
loan.user.setPersonalID(loan_User[2]);
for (int i = 1; i <= Integer.parseInt(splitOut[1]); i++) {
book = new Book(); // added this line
book.setName(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)]);
book.setAuthorFirstname(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)+1]);
book.setAuthorSurname(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)+2]);
book.setISBN(loan_CurrentLoans[((Integer.parseInt
(splitOut[1])-1)*4)+3]);
loan.currentLoans.put(i, book);
}
for (int i = 1; i <= Integer.parseInt(splitOut[3]); i++) {
book = new Book(); // added this line
book.setName(loan_Returned[((Integer.parseInt
(splitOut[3])-1)*4)]);
book.setAuthorFirstname(loan_Returned[((Integer.parseInt
(splitOut[3])-1)*4)+1]);
How I solved it;
public static void readLoans(){
// Reads the bookList and userList.
readBooks();
readUsers();
// Creates a new BufferedReader and tries to read "loans.txt"
BufferedReader reader = null;
try {
reader=new BufferedReader(new FileReader("loans.txt"));
}
// Catches exception if "books.txt" does not exist.
catch (FileNotFoundException e) {
e.printStackTrace();
}
String line = null;
// tries to read the first line and interpret it as a String.
try {
line = reader.readLine();
}
// Catches IOexception if any is thrown when trying to read line.
catch (IOException e) {
e.printStackTrace();
}
// Loop as long as "line" is not empty, i.e. as long as a Loan is read.
while (line!=null) {
// split the String "line" at every RegEx "-"
String[] splitOut=line.split("-");
// Create a String from the first index of the first split.
String user = splitOut[0];
/* Split the second and third index of the first split and create
* new Stringarrays from them.*/
String[] loans = splitOut[1].split(",");
String[] returns = splitOut[2].split(",");
User aUser = new User();
/* Find the user in the userList whose personal ID matches the
* String "user" that we created. This is the user that we want to
* create (a) loan/s and/or (a) returned loan/s for.*/
for (int i = 1; i < userList.size()+1; i++) {
if (userList.get(i).getPersonalID().equals(user)) {
/*Set the variables for the User.*/
aUser.setFirstname(userList.get(i).getFirstname());
aUser.setSurname(userList.get(i).getSurname());
aUser.setPersonalID(userList.get(i).getPersonalID());
aUser.setTelephone(userList.get(i).getTelephone());
aUser.setLoans(userList.get(i).getLoans());
aUser.setReturns(userList.get(i).getReturns());
// Create an ArrayList for Loans and Returns for every user
ArrayList<Loan> listOfloans = new ArrayList<Loan>();
ArrayList<Loan> listOfreturns = new ArrayList<Loan>();
// if the new user has any loans...
for (int j = 0; j < aUser.getLoans(); j++) {
for (int k = 1; k < bookList.size()+1; k++) {
/* ... find the "Book" object with the
* corresponding ISBN...*/
if (bookList.get(k).getIsbn().equals(loans[j*3])) {
// ...then create a new loan object for each...
Loan loan = new Loan();
// ...and set the variables of each loan...
loan.setTitle(bookList.get(k).getTitle());
loan.setAuthor_firstname(bookList.get(k).
getAuthor_firstname());
loan.setAuthor_surname(bookList.get(k).
getAuthor_surname());
try {
loan.setIsbn(bookList.get(k).getIsbn());
} catch (Exception e) {
e.printStackTrace();
}
loan.setMaxLoan(bookList.get(k).getMaxLoan());
loan.setOnLoan(bookList.get(k).getOnLoan());
loan.setAvailable(bookList.get(k).
getAvailable());
loan.setSignature(loans[j*3+1]);
loan.setTimestamp(loans[j*3+2]);
/* ...then add each one to the "listOfloans"
* ArrayList.*/
listOfloans.add(loan);
}
}
}
/* if the "listOfloans" ArrayList is not empty,
* add the loan to loanList with User as Key.*/
if (!listOfloans.isEmpty()) {
loanList.put(aUser, listOfloans);
}
// if the new user has any returned loans...
for (int j = 0; j < aUser.getReturns(); j++) {
for (int k = 1; k < bookList.size()+1; k++) {
/* ... find the "Book" object with the
* corresponding ISBN...*/
if(bookList.get(k).getIsbn().equals(returns[j*4])){
// ...then create a new loan object for each...
Loan loan = new Loan();
// ...and set the variables of each loan...
loan.setTitle(bookList.get(k).getTitle());
loan.setAuthor_firstname(bookList.get(k).
getAuthor_firstname());
loan.setAuthor_surname(bookList.get(k).
getAuthor_surname());
try {
loan.setIsbn(bookList.get(k).getIsbn());
} catch (Exception e) {
e.printStackTrace();
}
loan.setMaxLoan(bookList.get(k).getMaxLoan());
loan.setOnLoan(bookList.get(k).getOnLoan());
loan.setAvailable(bookList.get(k)
.getAvailable());
loan.setSignature(returns[j*4+1]);
loan.setTimestamp(returns[j*4+2]);
loan.setReturndate(returns[j*4+3]);
/* ...then add each one to the "listOfreturns"
* ArrayList.*/
listOfreturns.add(loan);
}
}
}
/* if the "listOfreturns" ArrayList is not empty,
* add the returned loan to returnList with User as Key.*/
if (!listOfreturns.isEmpty()) {
returnList.put(aUser, listOfreturns);
}
}
}
// tries to read the next line and interpret it as a String.
try {
line=reader.readLine();
}
// Catches IOexception if any is thrown when trying to read line.
catch (IOException e) {
e.printStackTrace();
}
}
// try to close the BufferedReader.
try {
reader.close();
}
// Catches IOexception if any is thrown when trying to close.
catch (IOException e) {
e.printStackTrace();
}
}
It was a problem with the instancing of the Book object and with objects and methods being static. I had to rewrite a few of the methods behind the scenes that were major problems. Thanks for all the help! =)

Unexpected output in java when using ArrayList<ArrayList<String>>()

I have the following code in java, which takes in input from the user. It is basically a simple database system.
ArrayList<String> commands = new ArrayList<String>();
ArrayList<ArrayList<String>> blocks = new ArrayList<ArrayList<String>>();
ArrayList<String> list = new ArrayList<String>();
System.out.println("Enter the transaction commands.\n");
Scanner scan = new Scanner(System.in);
while(!(line = scan.nextLine()).toLowerCase().equals("end"))
{
commands.add(line);
}
for(String com : commands)
{
String split[] = com.split(" ");
if(!split[0].toLowerCase().equals("get") && !split[0].toLowerCase().equals("numequalto") && !split[0].toLowerCase().equals("rollback") && !split[0].toLowerCase().equals("commit"))
{
if(split[0].toLowerCase().equals("begin"))
{
if(!list.isEmpty())
{
blocks.add(list);
System.out.println(blocks.get(0));
list.clear();
}
else
{
continue;
}
}
else
{
list.add(com);
continue;
}
}
}
System.out.println(blocks.get(0));
The input I give for this program is:
set a 10
set b 20
begin
get a
get b
end
While the expected output is:
[set a 10, set b 20]
[set a 10, set b 20]
I get the output as:
[set a 10, set b 20]
[]
The problem seems to be that the value of the ArrayList> blocks, seems to be overwritten. The last print statement prints the value as an empty ArrayList. I cannot find the exact source of error. Any help in finding out the error will be greatly appreciated.
I believe the following code is the culprit:
blocks.add(list);
System.out.println(blocks.get(0));
list.clear();
You add the list to blocks. Note, when you are adding your list object to blocks, you are not copying the list.
So when you clear the list, it clears the list object that is also referenced in the blocks list.
To avoid this you could just:
blocks.add(list);
System.out.println(blocks.get(0));
list = new ArrayList<String>();
This will create a new list object and leave the one in your blocks list untouched.
Your second output is got from last line of System.out.println(blocks.get(0));. Have a look at your code, you add blocks.add(list); after a while you clear the list. As List is mutable, so blocks List is empty. So, your second output print nothing.
blocks.add(list); //list has added here with values
System.out.println(blocks.get(0));
list.clear(); // list here without values.
This giving correct answer as you expected.
remove that list.clear() statement
import java.util.ArrayList;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
ArrayList<String> commands = new ArrayList<String>();
ArrayList<ArrayList<String>> blocks = new ArrayList<ArrayList<String>>();
ArrayList<String> list = new ArrayList<String>();
System.out.println("Enter the transaction commands.\n");
String line;
Scanner scan = new Scanner(System.in);
while (!(line = scan.nextLine()).toLowerCase().equals("end")) {
commands.add(line);
}
for (String com : commands) {
String split[] = com.split(" ");
if (!split[0].toLowerCase().equals("get")
&& !split[0].toLowerCase().equals("numequalto")
&& !split[0].toLowerCase().equals("rollback")
&& !split[0].toLowerCase().equals("commit")) {
if (split[0].toLowerCase().equals("begin")) {
if (!list.isEmpty()) {
blocks.add(list);
System.out.println("list :" + blocks.get(0));
// list.clear();
} else {
continue;
}
} else {
list.add(com);
continue;
}
}
}
System.out.println("output :" + blocks.get(0));
}
}
Answer i got is
list :[set a 10, set b 20]
output :[set a 10, set b 20]

How can I convert existing procedural code to use classes?

I'm trying to learn Java and basically my approach has been to take the procedural style I learned with python, and apply it to Java. So I never use classes and just put everything in a single class with many methods(which I just use as python functions). I think I've hit a problem, and need to bite the bullet and use classes, but I'm having trouble wrapping my head around how to do it.
To simplify my problem(ignore the poor design- it's just to illustrate the point), I have a program that takes a list and within a for loop does some math on each item(in this case adds 1 to the value of the list). I only want it to do work on 2 items on the list and then stop(in this example it's the first 2 items but in my real program it could be anywhere in the list). Here's the working code that is similar to how I'm already doing it:
No Classes:
public class LearningClasses {
public static void main(String[] args) {
int[] list = new int[]{1,2,3,4,5,6,7,8,9,10};
int[] data_list = new int[list.length];
for (int current_location = 0; current_location<list.length;current_location++) {
for (int i =0; i<100; i++){
if (check_size(data_list) == false ) {
break;
}
data_list[current_location] = (list[current_location]+1);
}
}
//its done now lets print the results
for (Integer item : data_list) {
System.out.println(item);
}
}
private static boolean check_size(int[] data_list) {
// TODO Auto-generated method stub
int count = 0;
for (int item : data_list) {
if (item != 0) {
count++;
if (count>=2) {
break;
}
}
}
if (count>=2) {
return false;
} else {
return true;
}
}
}
The problem with this code is although it works it's inefficient because it calculates the count on every iteration of the second for loop. In my program I cannot put anything above the first for loop but I can put anything below it, so I thought instead of doing the count every time maybe I could use a class to somehow maintain state and just increment the number as oppose to recalculating every time.
With classes:
public class LearningClassesCounter {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] list = new int[]{1,2,3,4,5,6,7,8,9,10};
int[] data_list = new int[list.length];
for (int current_location = 0; current_location<list.length;current_location++) {
//can only put commands in here. Nothing above.
Counter checker = new Counter(data_list);
System.out.println(checker.check_data());
for (int i =0; i<100; i++){
data_list[current_location] = (list[current_location]+1);
}
}
//its done now lets print the results
for (Integer item : data_list) {
System.out.println(item);
}
}
}
class Counter {
private int count; // current value
private boolean continue_or_not;
private int[] data_list;
// create a new counter with the given parameters
public Counter(int[] data_list) {
data_list = this.data_list;
count = 0;
continue_or_not = true;
}
public boolean check_data() {
// TODO Auto-generated method stub
int count = 0;
for (int item : data_list) {
if (item != 0) {
count++;
if (count>=3) {
break;
}
}
}
if (count>=3) {
return false;
} else {
return true;
}
}
// increment the counter by 1
public void increment() {
count++;
}
// return the current count
public int value() {
return count;
}
}
This doesn't work because it thinks the data_list is a null pointer(I know I'm declaring it null, but if I make it private int[] data_list = data_list it doesn't compile either). My ultimate goal is to have some kind of controls, in this case its limiting it to 2 items but I want to also add other limits like total value of al items cannot exceed X or cannot be lower than X and want to save CPU power by not having to do full calculations every time. So I think I need to be able to increment the values and then need to check that those increments haven't exceeded thresholds.
Can anyone help me understand what I'm doing wrong? Am I only wrong with syntax; or am I designing this wrong?
//can only put commands in here. Nothing above.
Counter checker = new Counter(data_list);
System.out.println(checker.check_data());
When you are calling checker.check_data(), its trying to parse through the data_list, but its empty. So, it throws a NullPointerException. The data_list is empty because inside your constructor, you may need to initialize like this this.data_list = data_list instead of data_list = this.data_list (here this.data_list has no reference so NULL)
If you avoid that call, the output will be 2,3,4,5,6,7,8,9,10,11.

Categories

Resources