Creating an incremental number sequence in Java - java

So I'm creating a student database thing for a school project. My first issue is that upon creating a new student I should see "Application number ### has registered successfully". Now the problem is that we have to have that number generate (### referring to the number) sequentially from 1 every time a new application is recorded. How would I go about doing that?
So far this is what there is but I can't seem to get the number to generate incrementally.
public TestApplication(String Surname, String personalIdNo)
{
if (isValidpersonalIdNo(personalIdNo) == true)
{
Student.add(Surname);
Application.put(personalIdNo, Student);
System.out.println("Application number ### " + "has registered successfully");
}
else
{
System.out.println("Application has failed, Personal id: " + personalIdNo);
}
}
Any help with this would be appreicated.

Since you seem to be using lots of static methods, I believe the best thing for you to do in this case is to create a static field called latestId and a static method called generateId, both in the Student class. Then you can call the generateId method whenever you call Student.add.
However, please note that this solution does not work if your application is multithread.
public class Student {
private static int latestId = 0;
public static int generateId() {
return ++latestId;
}
...
}

You can write a singleton class that will produce the ids for you:
class Generator {
private AtomicInteger count = new AtomicInteger(1);
private static Generator generator = new Generator();
private Generator() { }
public static Generator getInstance() {
return generator;
}
public int generate() {
return count.getAndIncrement();
}
}
Now, when you need to get a new id, you just call the generate method. The AtomicInteger is used because you might need the id from multiple threads and it will make the concurrent access safe.
The singleton Generator provides a single entry point to the id-generating facility.

You can use your storage type to give you the amount of added students that were put into DB.
I don't know what type you use to store your students. If it is hashmap or vector you can use size method to print students count. So I assume if you have Application.put you probably have a field in your Application type that is used to store each student. Then you can add a method like getStudentsCount to it and you should be all set. Since I don't know much about your Application type the above is all assumptions. Below you can find how I would solve that:
import java.util.HashMap;
import java.util.Vector;
class Student{
private String name;
private int personalID;
public Student(String name, int personalID){
this.name = name;
this.personalID = personalID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPersonalID() {
return personalID;
}
public void setPersonalID(int personalID) {
this.personalID = personalID;
}
}
class DB{
private HashMap<Integer, Student> students = new HashMap<Integer, Student>();
public boolean addStudent(Student student) {
Integer studentId = new Integer(student.getPersonalID());
if( !students.containsKey(studentId)){
students.put(new Integer(studentId), student);
return true;
}
else
return false;
}
public int getStudentCount() {
return students.size();
}
}
class Operations{
DB db;
public Operations(DB db){
this.db = db;
}
public boolean addStudent(String name, int personalID){
Student student = new Student(name, personalID);
return db.addStudent( student );
}
}
public class SimpleStudentDB {
public static void main(String [] args){
DB db = new DB();
Operations operations = new Operations(db);
if( operations.addStudent( "Jason", db.getStudentCount()+1) )
System.out.println("Student added successfully. DB contains ###"+db.getStudentCount()+" elements");
else
System.out.println("Operation failed");
}
}

Related

Looking through class Arraylist objects without nested loops

I had this object oriented programming project last semester and it was all about simulating a simple dormitory.
1.There should have been a manager class in which the main method and like 80 percent of the other methods had to be there.
2.A dormitory class containing an arraylist of blocks.
3.A block class containing an arraylist of rooms.
4.A room class containing an arraylist of students.
5.All of these classes contained getters and setters for their private variables.
There were a few methods that we should've added to the program which has nothing to do with my question,so I will not write them in here,but the thing is,a few of theses methods needed to look through these arraylists to find a specific object.For example,a student with a specific student number.I created these methods with nested loops.But I know there is some way I could avoid heavy nesting.
Here is my reduced code.I will only let the manager class contain one nested loop method as an example:
import java.util.Scanner;
public class Manager {
private String name;
private String familyName;
private String userName;
private String passWord;
private static Scanner scan = new Scanner(System.in);
private Dormitory dorm = new Dormitory();
private static Menu menu = new Menu();
private Student tempStudent;
private Block tempBlock;
private Room room;
private boolean bool;
{
dorm.setDormManager(this);
}
public Manager(String managerName, String managerID) {
name = managerName;
userName = managerID;
}
//find student with its number
public void findStudent() {
//Taking the student number from the user.
System.out.println("Please enter the student number:");
String studentNum = scan.nextLine();
for (int i = 0; i < dorm.getBlockList().size(); i++)
for (int j = 0; j < dorm.getBlockList().get(i).getRooms().size(); j++)
for (int k = 0; k < dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().size(); k++)
if (dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().get(k).getStudentNumber().equals(studentNum)) {
tempStudent = dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().get(k);
break;
}
}
public void create() {
//Used loops for the original program.
Block block1 = new Block("1");
Block block2 = new Block("2");
dorm.getBlockList().add(block1);
dorm.getBlockList().add(block2);
Room room1 = new Room("1");
Room room2 = new Room("2");
dorm.getBlockList().get(0).getRooms().add(room1);
dorm.getBlockList().get(1).getRooms().add(room2);
Student student1 = new Student("12345678");
Student student2 = new Student("98765432");
dorm.getBlockList().get(0).getRooms().get(0).getRoomStudents().add(student1);
dorm.getBlockList().get(1).getRooms().get(0).getRoomStudents().add(student2);
}
public static void main(String[] args) {
Manager manager = new Manager("Dumbledore", "#1112");
manager.create();
}
}
public class Dormitory {
private int blocks;
private Manager dormManager;
private long allMembers;
private ArrayList<Block> blockList = new ArrayList<Block>();
}
public class Block {
private String blockNumber;
private ArrayList<Room> rooms = new ArrayList<Room>();
private Dormitory dorm = new Dormitory();
public Block(String blockNum) {
blockNumber = blockNum;
}
}
public class Room {
private String roomNumber;
private ArrayList<Student> roomStudents = new ArrayList<Student>();
private Block roomBlock;
private Student roomManager;
public Room(String roomNum) {
roomNumber = roomNum;
}
}
public class Student {
private String studentName;
private String studentFamilyName;
private String studentNumber;
private Room room;
public Student(String studentNum) { //Creates a student object using the student number.
studentNumber = studentNum;
}
}
I tried my best to reduce the code.
I searched a lot and asked a lot of people about this but I didn't get my desired answer.I'm not sure why I couldn't find anything about this,but I'd really appreciate it if you'd lend me a hand or give me the link of a related article.
Short answer: No, you should never loop through everything checking for getStudentNumber().equals(studentNum). This has linear time complexity O(N)
Long answer: You should index your data based on your queries
Eg: Indexing with HashMaps which have constant time complexity O(1). (Note: This code is not thread safe)
public class SchoolService {
private Map<String, Student> studentsById = new HashMap<>();
private Map<Long, Dorm> dormsById = new HashMap<>();
/// dormsByAreaCode is showing an example of an index which groups objects into lists
private Map<String, List<Dorm>> dormsByAreaCode = new HashMap<>();
public void addStudent(Student student) {
if (studentsById.containsKey(student.getName()) {
throw new IllegalStateException("Duplicate student " + student.getName());
}
studentsById.put(student.getId(), student);
}
public Student getStudentById(String studentId) {
Student student = studentsById.get(studentId);
if (student == null) {
throw new IllegalStateException("No such student " + studentId);
}
return student;
}
public void addDorm(Dorm dorm) {
// TODO: validation
dormsById.put(dorm.getId(), dorm);
List<Dorm> areaDorms = dormsByAreaCode.get(dorm.getAreaCode());
if (areaDorms == null) {
areaDorms = new ArrayList<>();
dormsByAreaCode.put(dorm.getAreaCode(), areaDorms);
}
areaDorms.add(dorm);
}
public Dorm getDormById(long dormId) {
Dorm dorm = dormsById.get(id);
// TODO: validation
return dorm;
}
public List<Dorm> getDormsByAreaCode(String areaCode) {
List<Dorm> areaDorms = dormsByAreaCode.get(areaCode);
// TODO: validation
return areaDorms;
}
// etc
}
The following quote is from tutorialspoint. This is the perfect use case of the forEach method from the Stream interface. The link I provided and further reading on Streams can help avoid repetitive code.
Using collections framework in Java, a developer has to use loops and make repeated checks. Another concern is efficiency; as multi-core processors are available at ease, a Java developer has to write parallel code processing that can be pretty error-prone.
dorm.getBlockList().stream().forEach((b) -> {
b.getRooms().stream().forEach((r) -> {
...
})
});
You can also read about parallelStreams from here.

How to use setter to set a value to a attribute which is a private array?

I had made an array of roll number so how to give a user input using setter to the private attribute which is roll number.
I made an object of class Students which is a students and tried thisstudents.for(int i=0;i<n;i++)
{(setRollno[i](sc.next()))};
But it did not worked.
class Students{
private String[] rollno = new String[1000];
private int[] intel = new int[1000];
private int[] type = new int[1000];
private String[] name = new String[1000];
public void setRollno(String[] rollno) {
this.rollno = rollno;
}
public void setName(String[] name) {
this.name = name;
}
public void setIntel(int[] intel) {
this.intel = intel;
}
public void setType(int[] type) {
this.type = type;
}
public String[] getRollno() {
return rollno;
}
public String[] getName() {
return name;
}
public int[] getIntel() {
return intel;
}
public int[] getType() {
return type;
}
}
Possibly I'm misunderstanding the aim of your data structure, but it sounds like you're trying to create a collection of student data all in one place. If this is the case then I'd strongly recommend creating a Student class which represents just one student at a time, and then using one or more standard types from the Java Collection Framework to make it easy to find a particular student.
For example, your Student class could simply contain fields which hold the roll number, name, and other data for one student. Then, assuming that you'll want to find students quickly by roll number you could create a Map<String, Student> where the map keys are roll numbers and the corresponding map value is the student who has that roll number. Simply put a new Student object into the Map after constructing it. If you need to find students by name then you could create a Map<String, Collection<Student>> (because more than one student might have the same name) and put each new Student object into this name map after constructing it.
This is likely to lead to code which is a lot easier to read, maintain, and use than an all-in-one custom collection class such as the one shown in your question.
As a rough code example:
String rollNumber = getNewRollNumber(); // wherever roll numbers come from
String name = getStudentName(); // wherever the name comes from
Student newStudent = new Student(rollNumber, name, etc);
studentsByRollNumber.put(rollNumber, newStudent);
studentsByName.computeIfAbsent(name,
n -> new ArrayList<>(1)).add(student);
Student studentWithParticularRollNumber =
studentsByRollNumber.get("123456");
Collection<Student> studentsWithParticularName =
studentsByName.get("Perry, Fred");
The Map#computeIfAbsent method will create a new ArrayList under the given student name only if no entry already exists under that name, or will fetch the existing list if that name already exists in the map, and then will put the new student into the list.
Within the call to computeIfAbsent the lambda expression t -> new ArrayList<>(1) simply means "take the value of the map key, and whatever it is just create a new ArrayList of size one". It simply guarantees that if there is not already a Collection<Student> stored under the given student name then a new ArrayList<Student> will be created and stored there.
setRollno[i](sc.next()); isn't the good syntax. Your function setRollno take an array of strings as parameter, and change all the array you have. If that's what you want, you must pass an array of Strings as parameter:
If you want to set one specific String in your rollno, you must create another function:
setRollNoAtIndex(int i, String s) {
this.rollno[i] = s;
}
If you need to call this in a loop, you can then simply do:
for(int i=0; i < n ;i++) {
students.setRollNoAtIndex(i, sc.next());
}
As per Berger's comment:
The syntax you were trying to use was probably either:
for(int i=0; i < n ;i++) {
students.getRollno()[i] = sc.next();
}
or
String[] list = new String [1000];
for(int i=0; i < n ;i++) {
list[i] = sc.next();
}
students.setRollno(list);
I think that design of this class is not correct, because we have access to internal arrays directly. Moreover, in that case you do not have to init all these arrays on new instance creation. I offer a little bit another implementation of this class, that I found more suitable for this goal:
final class Students {
private static final int TOTAL = 1000;
private final Map<String, Student> students = new HashMap<>(TOTAL);
public void setName(String rollno, String name) {
getOrCreateStudent(rollno).name = name;
}
public void setIntel(String rollno, int intel) {
getOrCreateStudent(rollno).intel = intel;
}
public void setType(String rollno, int type) {
getOrCreateStudent(rollno).type = type;
}
public Set<String> getRollno() {
return students.keySet();
}
public String getName(String rollno) {
return students.getOrDefault(rollno, Student.NULL).name;
}
public int getIntel(String rollno) {
return students.getOrDefault(rollno, Student.NULL).intel;
}
public int getType(String rollno) {
return students.getOrDefault(rollno, Student.NULL).type;
}
private Student getOrCreateStudent(String rollno) {
Student student = students.get(rollno);
if (student == null)
students.put(rollno, student = new Student(rollno));
return student;
}
private static final class Student {
private static final Student NULL = new Student(null);
private final String rollno;
private int intel;
private int type;
private String name;
public Student(String rollno) {
this.rollno = rollno;
}
}
}

Multiple products in a single client(arrayList)

I've been asked to program a small online sales aplication.
It sounds very simple in theory (but it's been a hell for me). I'm just supposed to have an arrayList with about 5 products and then have a client buy 1 to 5 products and print the sales total.
public class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public String printInfo() {
return "Product: " + name + " Cost: " + price;
}
}
Then I have a client class:
public class Cliente {
private String name;
private int numPedido;
ArrayList<Producto> products = new ArrayList<Producto>();
public void listBuilder() {
Producto shirt = new Producto("Shirt", 30);
Producto tshirt = new Producto("T-Shirt", 40);
Producto sweater = new Producto("Sweater", 50);
}
public Cliente(String name, int numPedido) {
this.name = name;
this.numPedido = numPedido;
}
public Cliente() {
}
public String getName() {
return name;
}
public int getNumPedido() {
return (int) (Math.random() * 100);
}
public void addNewClient() {
name = JOptionPane.showInputDialog("Nombre: ");
}
public String printInfo() {
return "Nombre: " + name;
}
}
Right now I'm stuck thinking on how to make a client select a product and get that attached to him. I was thinking on making an arrayList of an arrayList but I'm sure that would complicate things. I know there is probably an easier way to connect them but I can't think of any. The option I have in mind is a method which shows numbers from 1 to 3(corresponding to each product) and when the user picks one it should return the price of the item.
Still not sure how to implement it in a way that the user can pick multiple products.
EDIT:
I also have an admin class that goes like this:
public class Admin {
private Client[] clientList;
public AdminPedidos() {
clientList = new Client[2];
}
public void AddContact() {
clienteList[0] = addProduct();
clienteList[1] = addProduct();
fillList();
}
public Cliente addProduct() {
String contactoString = JOptionPane.showInputDialog("Are you a new client? Press 1 if yes.");
if (contactoString.equals("1")) {
return new Cliente();
} else {
return new Cliente(); //just for testing
}
}
private void fillList() {
for (Client i : clientList) {
i.addNewClient();
}
}
public void printContact() {
for (Client i : clientList) {
System.out.println(i.printInfo());
}
}
}
You can have some purchaseProduct method attached to each Client.
public void purchaseProduct(Product product) { this.products.add(product); }
Then each Client you instantiate (Client client = new Client(name, id);) can add Products to his/her cart with the purchaseProduct method.
I'm assuming you are using some kind of user input method (Scanner). With that you can read the user's input of which Product they want and accordingly call the function with the right Product.
The listBuilder function doesn't quite make sense to me btw (and after your edit, it's really hard to make sense of what the Admin class should be/represent).
Edit: You would probably want to create an ArrayList<Product> which will be attached to each client, which you already have. I sense that you have a difficulty deciding where to put your actual Products. You should not put them inside your Client class for sure.
You should think about who/where they are going to be used. Probably in main right? So just instantiate them there first and then the Client could choose which one to purchase (via the method I introduced before):
client.purchaseProduct(product);

Java - Using an object inside an object

I am working on a project ( I had a problem yesterday and so many people helped me!) so I decided to ask for help again.
My code has 3 classes. ProjectMain,Students,Classroom. I created an array of Classroom objects. Right now I have 3 Classroom objects. But I have to assign student objects to these Classroom objects. For example : classarray[0] is an object from Classroom class and studentobject.get(0) , studentobject.get(1) ... will be students objects inside classarray[0] object. But I have failed on this while coding. Here are my classes :
public class Classroom
{
private String classname;
private String word[] = null;
protected ArrayList<Students> studentobject = new ArrayList<Students>(10);
public String[] getWord()
{
return word;
}
public void setWord(String[] word)
{
this.word = word;
}
public ArrayList<Students> getStudentobject()
{
return studentobject;
}
public void setStudentobject(ArrayList<Students> studentobject)
{
this.studentobject = studentobject;
}
public String getClassname()
{
return classname;
}
public void setClassname(String classname)
{
this.classname = classname;
}
public void classroomreader(String filename)
{
// This method gets the name of Classroom
File text = new File("C:/Users/Lab/Desktop/classlists/" + filename
+ ".txt");
Scanner scan;
try
{
scan = new Scanner(text);
String line = scan.nextLine();
word = line.split("\t");
line = scan.nextLine();
word = line.split("\t");
} catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
}
}
This is my student class :
public class Students extends Classroom
{
private String name,id;
private int age;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
And my main class :
public class ProjectMain
{
public static void main(String[] args)
{
Classroom[] classarray = new Classroom[3];
//I got 3 Classroom objects here
classarray[0]=new Classroom();
classarray[1]=new Classroom();
classarray[2]=new Classroom();
classarray[0].classroomreader("class1");
classarray[0].studentobject.get(0).setName(classarray[0].getWord()[1]);
//The problem is in here. When my code comes to the line above,
// at java.util.ArrayList.rangeCheck(Unknown Source) error comes out.
// I tried to get first object in studentobject Arraylist, and tried to set it's name
// to the variable which my text reader reads.
How can I write what I have in my mind?
Your classroomreader method reads the file but don't do much of it... maybe you want to create some instance of Students within it.
scan = new Scanner(text);
String line = scan.nextLine();
word = line.split("\t"); // won't be used
line = scan.nextLine();
word = line.split("\t"); // erased here
There you only have the last line (split) of the file in word attribute.
When creating Classroom instance studentobject list is created empty and it stays that way so you can't access first (or any) object in it.
To populate your list you may add to Classroom method like this:
public void addStudent(Student s)
{
studentobject.add(s);
}
classroom contains the following field declaration
String word[] = null;
the main class, incl the classroomreader does not set a value to this field. Yet you are going to invoke
classarray[0].getWord()[1]
which then must fail.
tip: don't use expressions like this, which can be found in your main class (at least not in early stages of development, or learning)
classarray[0].studentobject.get(0).setName(classarray[0].getWord()[1]);
resolve into variables and several steps. Compilers are smart enough to produce the same code if the context is not disturbed, ie the long expression is resolved into a single block.
Never forget that the purpose of programming languages is to make programs readable for humans. :) Code with abbreviations or "tricks" simply shows some philodoxical attitude (imho)

Arraylist Java Binding errors

I need to create my own registry for a school project.
I would like to have
1
room, room
2
room, room
hall, hall
3
room, room
hall, hall
dorm, dorm
But all I am getting is
1
room,room
2
room,hall
hall,hall
3
room,dorm
hall,dorm
dorm,dorm
So somehow the the facility reference got changed somewhere but i have no idea how to fix this. Can anyone help?
These are my codes.
public class registry {
static List<registryRecord> register = new ArrayList<registryRecord>();
public static boolean bind(String name, facility ref){
for(registryRecord r:register){
if(r.name.equals(name)) //check if the name is already binded
return false;
}
registryRecord newRecord = new registryRecord(name, ref);
register.add(newRecord);
for (registryRecord r:register){
System.out.println(r.name +","+ r.ref.name);
}
return true;
}
public class registryRecord {
String name;
facility ref;
public registryRecord(String name, facility ref){
this.name = name;
this.ref = ref;
}
public class server {
public static void main(String args[]) throws Exception{
facility room = new facility("room");
System.out.println(1);
boolean test = registry.bind("room", room);
facility hall = new facility("hall");
System.out.println(2);
boolean test2 = registry.bind("hall", hall);
facility dorm = new facility("dorm");
System.out.println(3);
registry.bind("dorm", dorm);
}
public class facility {
public static String name;
static List<booking> bookings;
public facility(String name){
this.name=name;
this.bookings = new ArrayList<booking>();
}
}
As I suspected, since name is static in facility, it is shared between all instances. This means that it gets overwritten each time you create a new instance.
Just remove static from both your fields, and your program should work fine.

Categories

Resources