Collections/Menu - java

List<Student> studentInfo = new LinkedList<Student>();
int choice;
boolean flag = true;
Student student = new Student();
while(flag)
{
System.out.println();
System.out.println("Press 1 to Add Student details");
System.out.println("Press 2 to Display Student details");
System.out.println("Press 3 to Sort");
System.out.println("Press 4 to Search");
System.out.println("Press 5 to Exit");
System.out.println("Enter your choice: ");
choice = sc1.nextInt();
switch(choice)
{
case 1: studentInfo.add(student.addDetails());
break;
case 2: System.out.println("Details of Students are as follows: ");
for(Student s : studentInfo){
System.out.println(s);
}
break;
//More code
The addDetails() method in the Student class is:
public Student addDetails()
{
System.out.println("Enter the name: ");
name = sc2.nextLine();
this.setName(name);
return this;
}
I'm using the case 1 block to take the student details and then adding them into the studentInfo collection. But, when i display the last entered details overwrites all the previous ones and when i print them out only that is displayed as many number of students that I've added. Can somebody tell me what is that I've done incorrectly? Thanks!
OUTPUT:
Details of Students are as follows:
name=Amar, age=0, semester=0, sub_1_marks=0, sub_2_marks=0, sub_3_marks=0, percentage=0, totalMarks=0
name=Amar, age=0, semester=0, sub_1_marks=0, sub_2_marks=0, sub_3_marks=0, percentage=0, totalMarks=0

The fact that you are unsure of the answer to this question implies that it's answer may change as your code develops. If you focus on the fact that your code develops as time goes on you will often see the right path.
To me, this code already has an issue. The fact that if you wanted to add a new menu option you would have to add code in two different places (the print list and the case statement).
I would start by pulling those two areas back together into a single list of actions. Something like this:
static boolean exit = false;
enum Action {
AddDetails("Add student details") {
#Override
public void doIt() {
// How to add details.
}
},
DisplayDetails("Display student details") {
#Override
public void doIt() {
// How to display details.
}
},
SortDetails("Sort") {
#Override
public void doIt() {
// How to sort details.
}
},
SearchDetails("Search") {
#Override
public void doIt() {
// How to search details.
}
},
Exit("Exit") {
#Override
public void doIt() {
// How to exit.
exit = true;
}
};
private final String description;
Action(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public abstract void doIt();
}
public static void main(String args[]) {
try {
Scanner sc1 = new Scanner(System.in);
do {
// Show my menu.
for (Action a : Action.values()) {
System.out.println("Press " + a.ordinal() + " to " + a.getDescription());
}
System.out.println("Enter your choice: ");
int choice = sc1.nextInt();
// Should really do some range checks here.
Action action = Action.values()[choice];
// Perform the chosen function.
action.doIt();
} while (!exit);
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
So - in answer to your question - use the static methods mechanism but only the concept. Enums are a good substitute if you have a number of distinct actions.

Related

How to stop the program when pressing a certain button on the keyboard, for example s

I am new to programming and at the moment I am doing a task, the essence of which is the emulation of scanning a person by gender and age with a further pass to a zone defined for its parameters. I was told to supplement the program so that, for example, when you press the S button on the keyboard, the program ends.
Please tell me how can I implement this. I have 4 classes in my code:
main
public class Main {
public static void main(String[] args) {
PassportScan passportScan = new PassportScan();
Guard guard = new Guard();
while (true) {
Person person = passportScan.methodScan();
String result = guard.checkPerson(person);
System.out.println(result);
}
}
}
PassportScan
import java.util.Scanner;
public class PassportScan {
Scanner scanner = new Scanner(System.in);
public Person methodScan() {
System.out.println("Scanning gender");
String gender = scanner.next();
System.out.println("Scanning age");
int age = scanner.nextInt();
return new Person(gender, age);
}
}
Person
public class Person {
private String gender;
private Integer age;
public Person(String gender, Integer age) {
this.gender = gender;
this.age = age;
}
public String getGender() {
return gender;
}
public Integer getAge() {
return age;
}
}
Guard
public class Guard {
public String checkPerson(Person personToCheck) {
String gender = personToCheck.getGender();
int age = personToCheck.getAge();
if (age < 18 && gender.equals("M")) {
return "Zone 1";
}
if (age >= 18 && gender.equals("M")) {
return "Zone 2";
}
if (age < 18 && gender.equals("F")) {
return "Zone 3";
}
if (age >= 18 && gender.equals("F")) {
return "Zone 4";
}
return "";
}
}
Thanks in advance for the tip and your time!
Basically there will be two scenario for this.
1. Once Press S >>> You want to terminate the program
Simply its not available in normal console
but there is way to achieve refer this post for more info https://stackoverflow.com/a/1066647/8524713
2. Press S and then press Enter key >>
In this case its easy
check on each gender input if its S break the loop
try below code for reference
public static void main(String[] args) {
PassportScan passportScan = new PassportScan();
Guard guard = new Guard();
while (true) {
Person person = passportScan.methodScan();
//checking if person object is null if ts null means s is enter
// break from loop
if(person==null) {
break;
}
String result = guard.checkPerson(person);
System.out.println(result);
}
}
static class PassportScan {
Scanner scanner = new Scanner(System.in);
public Person methodScan() {
System.out.println("Scanning gender");
String gender = scanner.next();
//check if string input is S or s
// then its returning null person object
if(gender.equalsIgnoreCase("s")) return null;
System.out.println("Scanning age");
int age = scanner.nextInt();
return new Person(gender, age);
}
}
one more way is to directly terminate in PassportScan class once S is typed
class PassportScan {
Scanner scanner = new Scanner(System.in);
public Person methodScan() {
System.out.println("Scanning gender");
String gender = scanner.next();
//check if string input is S or s terminating prog
if(gender.equalsIgnoreCase("s")) System.exit(0)
System.out.println("Scanning age");
int age = scanner.nextInt();
return new Person(gender, age);
}
}
You probably have some Component in that you display something, for example a (class that extends) JFrame, lets call it c.
Now call:
c.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if (Character.toLowerCase(e.getKeyChar()) == 's') System.exit(0);
}
#Override
public void keyReleased(KeyEvent e) {
}
});
It is not possible to catch a KeyEvent without a GUI (When you think about it, how should Java know that the key was pressed in your application? If it would catch any KeyEvent on the device, you could easily build spyware that catches passwords or sth.)

validate private variable of another class when giving input

hello I have written code where it takes book details using setter method and displaying details using getter method. When user enters the input it has to enter three details.
Book NameBook PriceAuthor Name
I want to check if user has given any negative value or Zero value in Book Price.
How do I do that? Below is the code. I am practicing Encapsulation problem
//Book.java file
class Book
{
private String bookName;
private int bookPrice;
private String authorName;
public String getBookName()
{
return bookName;
}
public int getBookPrice()
{
return bookPrice;
}
public String getAuthorName()
{
return authorName;
}
public void setBookName(String a)
{
bookName=a;
}
public void setBookPrice(int b)
{
bookPrice=b;
}
public void setAuthorName(String c)
{
authorName=c;
}
}
//TestBook.java file
import java.util.*;
class TestBook
{
public static void main(String args[])
{
Book bobj = new Book();
Scanner sc = new Scanner(System.in);
try
{
System.out.println("Enter the Book name:");
bobj.setBookName(sc.nextLine());
System.out.println("Enter the price:");
bobj.setBookPrice(sc.nextInt());
sc.nextLine();
System.out.println("Enter the Author name:");
bobj.setAuthorName(sc.nextLine());
System.out.println();
System.out.println("Book Details");
System.out.println("Book Name :"+bobj.getBookName());
System.out.println("Book Price :"+bobj.getBookPrice());//should not be -ve or 0
System.out.println("Author Name :"+bobj.getAuthorName());
}
catch(Exception e)
{
System.out.println("Invalid Input");
}
}
}
You should put this check in your setter method to check if it is greater than zero. For example:
public void setBookPrice(int b)
{
if(b>0)
bookPrice=b;
else
{
throw new IllegalArgumentException("b must be positive")
}
}
Above code will prevent setting of negative and zero price. You can replace exception throwing code with your own handling.
If you are practising encapsulation I suggest creating a specific validation method for the price so this can be easily modified without changing the public interface.
public boolean isValidPrice() {
return bookPrice > 0;
}
This can now be checked with
if (!bobj.isValidPrice()) {
//error handling
}
And if the validation rules for price would change the calling code will remain unchaged

Understanding ArrayLists and Objects

Let's suppose I've the following Class Product:
public class Product {
// Variables.
private String name; // Name
private Double price; // Price
Product() {} // Default constructor with no parameters.
Product(String name, Double price) { // Constructor with parameters.
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price= price;
}
public String toString() { // Overriding "toString()".
return "\nName: " + this.name + "\nPrice: " + this.price;
}
public boolean equals(Object obj) { // Overriding equals()
if(this == obj) {
return true;
}
if(obj == null || obj.getClass() != this.getClass()) {
return false;
}
Product product = (Product) obj;
return this.name.equals(product.name)&& this.price.equals(product.price);
}
}
Now, let's suppose I've an ArrayList in my Main.class and my Main looks something like this:
import java.util.*;
import java.io.*;
public class Main {
private static BufferedReader r = new BufferedReader (new InputStreamReader(System.in));
private static String readln() throws IOException{
return r.readLine();
}
private static long readInput() throws IOException{ // Use this to read input for the menu options.
return Integer.valueOf(readln());
}
public static void menu(){ // Menu
System.out.println("-------------------------" +
"\nAdd new product(1)" +
"\nSearch for product(2)" +
"\nDelete product(3)" +
"\nShow all products(4)" +
"\nReturn the number of products(5)" +
"\nExit(-1)" +
"\n-------------------------");
}
public static void main (String args[]) throws IOException{
// This is the ArrayList for the "Product".
ArrayList<Product> products = new ArrayList<Product>();
int option = 0;
do {
menu();
option = (int)readInput();
switch (option){
case 1:{
System.out.println("Insert product name: ");
String name= readln();
System.out.println("Insert product price: ");
Double price = Double.parseDouble(readln());
products.add(new Product(name, price));
break;
}
case 2:{
System.out.println("Insert product name: ");
String name= readln();
System.out.println("Insert product price: ");
Double price= Double.parseDouble(readln());
if ((products.contains(new Product (name, price)))){
System.out.println("Works!");
}
break;
}
case 3:{
break;
}
case 4:{
break;
}
case 5:{
System.out.println("Number of products: " + products.size());
//This prints with no problems, therefor the objects DO exist in the ArrayList.
break;
}
}
}while((option > 0) && (option < 6));
}
}
According to this in order to insert an object into an ArrayList you need to write it like this "ArrayListName.add(new ObjectName(param1, param2));" or you can create an object called object1 and then add it with ArrayListName.add(object1); In my case, from what I understand, I'm inserting objects into the ArrayList but those objects do not really exist, because if I tried to use the overridden toString() method, it does not print anything. If my understanding is wrong, why does it not print anything? According to this, my method is correct.
If I've understood this correctly, objects do not need a variable to point to them, but if you've directly inserted them into an ArrayList, like I have, how are you supposed to get the index position of an object? Because the equals() in my case, compares objects, so you can't use it to search the ArrayList. Nor can you try something like "products.contains(name, price);" because, .contains() uses equals().
I was also thinking of doing something like this, but it's only useful if you want to create a new Class and not an object like product1, in my case. I gave up on it as well because forName() kept saying that it can't find the Class for some reason that I could not find out why.
What about the "Delete" option? Would it work the same way as the "Search" one?
Edit: for the equals() the last line, you can also put:
if( (this.price.equals(product.getPrice())) && (this.name.equals(product.getName())) ) {
return true;
}
To make it work you should also rewrite your equals method to compere fields inside people object overriding equals method
There could be a bug in your parametrized constructor. It should looks like:
Product(final String name, final Double price) { // Constructor with parameters.
this.name = name;
this.price = price;
}
Final word prevent us to change value of incoming parameter.
According to the article above the implementation should be
#Override
public boolean equals(Object obj) { // Overriding "equals()".
// at first check if objects are the same -> your code
if (this == obj) {
return true;
}
// secondly we chack if objects are instances of the same class if not return false
if (obj != null && this.getClass() != obj.getClass()) {
return false;
}
// then compare objects fields. If fields have the same values we can say that objects are equal.
Product product = (Product) obj;
return this.name.equals(product.name) && this.price.equals(product.price);
}
To handle nulls in fields we can write additional checks.
With new implementation of equals method to search for the element on the list you can pass new instance of product to contains mathod
instead of doing
products.contains(name, price);
try
products.contains(new Product(name, price))
To delete element from the list you can first find index of element and the use remove method.
products.remove(products.indexOf(new Product(name, price)))
Actually, this is not good example to understand of working with ArrayList. First of all, this collection is not good for product list. Yes, you could use it, but Map is much better. I do not think, that you're learning Java. If so, I prefer to use Map instead of List.
Moreover, I recommend to avoid using option numbers. Use named constants as minimum, but using OOP is much better. E.g. you could use enum where each element is one menu option.
E.g. like below.
public class Main {
public static void main(String... args) {
List<Product> products = readProducts();
// final list of products
}
private static List<Product> readProducts() {
Map<String, Product> products = new LinkedHashMap<>();
try (Scanner scan = new Scanner(System.in)) {
while (true) {
MenuItem.show();
MenuItem menuItem = MenuItem.parseOption(scan.nextInt());
if (menuItem == MenuItem.EXIT)
break;
menuItem.action(products, scan);
}
}
return products.isEmpty() ? Collections.emptyList() : new ArrayList<>(products.values());
}
private enum MenuItem {
ADD_NEW_PRODUCT(1, "Add new product") {
#Override
public void action(Map<String, Product> products, Scanner scan) {
System.out.println("Insert product name: ");
String name = scan.next();
System.out.println("Insert product price: ");
double price = scan.nextDouble();
if (products.containsKey(name))
products.get(name).setPrice(price);
else
products.put(name, new Product(name, price));
}
},
SEARCH_FOR_PRODUCT(2, "Search for product"),
DELETE_PRODUCT(3, "Delete product") {
#Override
public void action(Map<String, Product> products, Scanner scan) {
System.out.println("Insert product name: ");
String name = scan.next();
products.remove(name);
}
},
SHOW_ALL_PRODUCTS(4, "Show all products"),
RETURN_THE_NUMBER_OF_PRODUCTS(5, "Return the number of products") {
#Override
public void action(Map<String, Product> products, Scanner scan) {
System.out.println("Number of products: " + products.size());
}
},
EXIT(-1, "Exit");
private final int option;
private final String title;
MenuItem(int option, String title) {
this.option = option;
this.title = title;
}
public void action(Map<String, Product> products, Scanner scan) {
}
public static MenuItem parseOption(int option) {
for (MenuItem menuItem : values())
if (menuItem.option == option)
return menuItem;
return EXIT;
}
public static void show() {
System.out.println("-------------------------");
for (MenuItem menuItem : values())
System.out.printf("%s(%d)\n", menuItem.title, menuItem.option);
System.out.println("-------------------------");
}
}
}

How would I create a LinkedList, then create a value from input. Then if input matches value in LinkedList return that value?

Below is my code, I want to create a Linkedlist, with input from a user. ONce the user has inputed values into the LinkedList(accounts). He can then search for those values in a LinkedList, if those values(account name) he inputed match those in the linkedList, then that value become the new account selected.
How can I finish my choose method.
import java.util.*;
public class Customer {
public static void main(String[] args) {
new Customer();
}
private LinkedList<Account> accounts = new LinkedList<Account>();
public Customer() {
setup();
}
private void setup() {
accounts.add(new Account("",0.0));
accounts.add(new Account("",0.0));
accounts.add(new Account("",0.0));
}
public void use() {
char choice;
while((choice = readChoice()) != 'x') {
switch(choice) {
case 'a': choose(); break;
case 'i': addInterest(); break;
case 's': show(); break;
default: help();
}
}
}
private char readChoice() {
return 'x';
}
private void choose() {
for (Account account: accounts) {
}
}
private String readName() {
System.out.print("??? account ???; ");
return In.nextLine();
}
private Account account(String name) {
return null;
}
private void addInterest() {
for (Account account: accounts) {
for (int i = 0; i < 30; i++)
account.addDailyInterest();
account.addMonthlyInterest();
}
}
private void help() {
String s = "The menu choices are";
s += "\n a: choose an account";
s += "\n i: add interest to all accounts";
s += "\n s show";
s += "\n x exit";
System.out.println(s);
}
private void show() {
System.out.println(this);
}
public String toString() {
String s = "";
return s;
}
}
As I understand your problem logic, you want to be able to choose an account by name and set it as current. To do that you need to add a member to your Customer class that will store this selected Account, e.g.
Account selected; // null by default
Then the choose() method should loop through all accounts in order to find a match:
void choose(String name) {
Account found = null;
for (Account acc : accounts) {
if (acc.getName().equals(name)) {
found = acc;
}
}
if (found) {
selected = found;
}
else {
System.out.println(name + " not found in list.");
}
As a suggestion, you can have show() that will display the account information from the selected (if it exists), and a showAll() that can display all accounts.
You need also to initialise properly the accounts list and write the logic in the main().

Linking array with Subclasses [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
my current program is a pupil library system, I have my array lists, menus and methods which all work. My problem is i need the arrays to be reading from the superclass LoanBook which takes in overrides from the Subclasses (Fiction and NonFiction).
As you can see from the AddBook method, it takes in details of the book and stores to an array list.
My Question :
I need to add the option Fiction or Non-Fiction but i need the arraylist take take property's from the Superclass and SubClasses. Can i get some help please.
Im happy to answer any questions you may have or provide more information.
Main Class
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
import java.util.Scanner;
public class Main{
static Scanner keyboard = new Scanner(System.in);
static boolean run = true;
static Formatter x;
public static void main(String[]args){
LoanBook myBook = new LoanBook();
while (run){ // this while statement allows the menu to come up again
int answer = 0;
boolean isNumber;
do{ // start of validation
System.out.println("1. Add book");
System.out.println("2. Display the books available for loan");
System.out.println("3. Display the books currently on loan");
System.out.println("4. Make a book loan");
System.out.println("5. Return book ");
System.out.println("6 Write book details to file");
if (keyboard.hasNextInt()){ // I need to consider putting in a =>1 <=6
answer = keyboard.nextInt();
isNumber = true;
} else {
System.out.print(" You must enter a number from the menu to continue. \n");
isNumber = false;
keyboard.next(); // clears keyboard
}
}
while (!(isNumber));
switch (answer){
case 1:
addBook();
break;
case 2:
viewAll();
break;
case 3:
booksOnLoan();
break;
case 4:
loanBook();
break;
case 5:
returnBook();
break;
case 6:
writeToFile();
break;
case 7:
break;
}
}
}
static List<String>pupilName = new ArrayList<String>();
static List<String>issueDate = new ArrayList<String>();
static List<String>bookTitle = new ArrayList<String>();
static List<String>bookAuthor = new ArrayList<String>();
static List bookOnloan = new ArrayList<Boolean>();
public static void viewAll(){
System.out.println("\n");
for (int x = 0; x < bookTitle.size();x++){
int counter = x+1;
System.out.println("BookID:" +counter + "\n " + bookTitle.get(x) + " - " + bookAuthor.get(x)+" " + bookOnloan.get(x));
}
}
public static void booksOnLoan(){
System.out.println("\n");
for (int x = 0; x < pupilName.size();x++){
if (bookOnloan.contains(true)){
int counter = x+1;
System.out.println("BookID:" +counter + "\n "+"Pupil name: " + pupilName.get(x)
+"\n Book Title: "+ bookTitle.get(x) + " by " + bookAuthor.get(x)+" " + bookOnloan.get(x)+ "\n Issued: "+ issueDate.get(x)) ;
}
}
}
public static void addBook(){
System.out.println("Please enter the book title: ");
String newTitle = keyboard.next();
bookTitle.add(newTitle);
System.out.println("Please enter the book author");
String newAuthor = keyboard.next();
bookAuthor.add(newAuthor);
bookOnloan.add(false);
System.out.println("\n Your book: "+ bookTitle.get(bookTitle.size()-1)+ " has been added to the library" + "\n");
}
public static void loanBook(){
viewAll();
System.out.println("Please choose the BookID you would like to issue: ");
int issue = keyboard.nextInt()-1;
if (issue > 10){
System.out.println("Invalid book selection");
}
else {
bookOnloan.set(issue,true);
System.out.println("Please enter pupil name: ");
String newPupil = keyboard.next();
pupilName.add(newPupil);
System.out.println("Please enter date of issue: ");
String newIssue = keyboard.next();
issueDate.add(newIssue);
}
}
public static void returnBook(){
// booksOnLoan();
System.out.println("Please choose the BookID you would like to return: ");
int issue = keyboard.nextInt()-1;
if (issue > 10){
System.out.println("Invalid book selection");
}
else {
bookOnloan.set(issue,false);
Next is my Superclass
public class LoanBook {
private int bookID;
private String title,author,name,date;
boolean onLoan;
private static int count = 0;
static List<String> bookTitle = new ArrayList<String>();
static List<String>bookAuthor = new ArrayList<String>();
static List<String> pupilName = new ArrayList<String>();
static List<String>issueDate = new ArrayList<String>();
static List bookOnloan = new ArrayList<Boolean>();
public LoanBook(String title,String author){ //constructor
this.bookID = count;
this.author = author;
this.title = title;
bookOnloan.add(false);
count++;
}
public void setTitle(String title){
bookTitle.set(1,title);
}
public String getTitle(){
return bookTitle.toString();
}
public void setAuthor(String author){
bookTitle.set(1,author);
}
public String getAuthor(){
return bookAuthor.toString();
}
public String getName(){
return pupilName.toString();
}
public void setName(String name){
pupilName.set(1,name);
}
public String getDate(){
return issueDate.toString();
}
public void setDate(String date){
issueDate.set(1,date);
}
public Boolean getOnloan(){
return bookOnloan.add(false);
}
public void setOnLoan(Boolean onLoan){
bookOnloan.add(false);
}
}
Next my subclasses
public class Fiction extends LoanBook {
private String type;
public Fiction(){
}
public Fiction(String title,String author, String type){
super(title,author); //calls constructor of the superclass
this.type = type;
}
public void setType(String type){
type = "Fiction";
}
public String getType(){
return type;
}
public String toString(){
return super.toString() + " The book type is: " + getType()+"\n";
}
}
and the other subclasss
public class NonFiction extends LoanBook {
private String type;
public NonFiction(){
}
public NonFiction(String title,String author, String type){
super(title,author); //calls constructor of the superclass
this.type = type;
}
public void setType(String type){
type = "Fiction";
}
public String getType(){
return type;
}
public String toString(){
return super.toString() + " The book type is: " + getType()+"\n";
}
}
Your whole program structure is broken from your over-use of static fields to your mis-use of inheritance, to your combining the concepts of a Book and a Book collection all in one class.
Suggestions:
Don't mix your Book class with your Book collection. This looks to be the primary problem with your code.
Start with just a Book class. It should contain no lists at all.
You can have FictionBook and NonFictionBook extend Book if so desired.
Or you could simply give Book a boolean field, fiction, and set it to true or false depending on the needs.
Create a LoanBook class that holds List of Books.
Don't use inheritance unless a true "is-a" relationship exists. Your code does not satisfy this mainly due to your first problem, your mixing your Book class together with your Book Library code, which forces your Fiction book and your non-Fiction book to inherit library code which is not only not needed, but really detrimental.
Avoid use of static anythings, unless they are there for a specific static purpose.
You will likely be best served by trashing your current code and re-starting over.

Categories