Random selection from array list [duplicate] - java

This question already has answers here:
What is a raw type and why shouldn't we use it?
(16 answers)
Closed 5 years ago.
I want to select a student randomly for messfood(). Trying to print the student name there.Each week, any of the student should be selected for mess food charge. Tried with String random = list.get(new Random().nextInt(list.size()));. But is shows error. Help me with this.
public class Student {
int rollNo, yearOfStudy;
String fName, lName, activity;
Student(int rollNo, String fName, String lName, int yearOfStudy) {
this.rollNo = rollNo;
this.fName = fName;
this.lName = lName;
this.yearOfStudy = yearOfStudy;
}
public void display(){
System.out.println("Roll Number: "+rollNo +"\nName: "+fName+ " "+lName + "\nYear Of Study: "+yearOfStudy+"\n\n");
}
public void messFood(){
System.out.println("week 1, Mess food Incharge: ");
}
}
class Collection {
public static void main(String[] args) {
Student s1 = new Student(1, "Alex", "Iwobi", 2013);
Student s2 = new Student(2, "Denis", "Suarez", 2013);
Student s3 = new Student(3, "Gerard", "Deulofeu", 2013);
Student s4 = new Student(4, "Petr", "Cech", 2013);
List studentList = new ArrayList();
studentList.add(s1);
studentList.add(s2);
studentList.add(s3);
studentList.add(s4);
Iterator it = studentList.iterator();
while(it.hasNext()){
Student s=(Student)it.next();
s.display();
}
}
}

This is precisely why you should be using generics! You risk to encounter runtime errors (as opposed to compile-time errors) involving expected and actual types.
Your call to list.get() will return Object if generics are not used, requiring you therefore to cast it. If the cast happens to be wrong as in your case, it will explode only when run. If you were using generics, your compiler would have told you that you can't convert a Student type to String type!
Take a look at my version:
public class Student {
int rollNo, yearOfStudy;
String fName, lName, activity;
public Student(int rollNo, String fName, String lName, int yearOfStudy) {
this.rollNo = rollNo;
this.fName = fName;
this.lName = lName;
this.yearOfStudy = yearOfStudy;
}
#Override
public String toString() {
return new StringBuilder()
.append("Roll Number: ").append(rollNo)
.append("\nName: ").append(fName).append(" ").append(lName)
.append("\nYear Of Study: ").append(yearOfStudy)
.append("\n\n")
.toString();
}
public void messFood() {
// Establish mess food charge role
}
public static void main(String[] args) {
Student s1 = new Student(1, "Alex", "Iwobi", 2013);
Student s2 = new Student(2, "Denis", "Suarez", 2013);
Student s3 = new Student(3, "Gerard", "Deulofeu", 2013);
Student s4 = new Student(4, "Petr", "Cech", 2013);
List<Student> studentList = new ArrayList<Student>();
studentList.add(s1);
studentList.add(s2);
studentList.add(s3);
studentList.add(s4);
Iterator<Student> it = studentList.iterator();
while (it.hasNext()) {
Student s = it.next();
System.out.println(s.toString());
}
Student randomStudent = getRandomItem(studentList);
randomStudent.messFood();
System.out.println("week 1, Mess food Incharge: ");
System.out.println(randomStudent.toString());
}
private static <T> T getRandomItem(List<T> studentList) {
return studentList.get(new Random().nextInt(studentList.size()));
}
}
Also, in addition to generics, I added a couple of best practices, namely prefering the use of toString() to describe the class rather than printing it out directly (you can do with the String whatever you want afterwards, including calling System.out.println()) .
Also I moved out printing from messFood because again, it is generally preferable to do so. Hope that helps!
Edit: Describing briefly getRandomItem, try not to get too caught up in the details, but <T> says that there will be a type to replace T according to how it will be called. Based on how it is defined, it says if you pass me a List containing type T, I will return to you an object T. T in this case translates to Student, but I kept it generic because it works equally well with other lists. For all intents and purposes, it is as if the signature were the following:
private static Student getRandomItem(List<Student> studentList)

list.get()
will return a student object and not a string, assuming that it's a list of students.
You should do
Student random = list.get(new Random().nextInt(list.size()));
System.out.println(random.getFname + " " + random.getLname);
But of course you need get methods defined.

Related

Proper use of objects

I have this method addPerson (on the main) which is used to set the name of a person.
private static Person[] addPerson(Person _person[], int _minAge, int _id){
int personAge;
String personName;
Scanner scan = new Scanner(System.in);
System.out.println("What's his age?");
personAge = scan.nextInt();
if(personAge >= _minAge){
if(!_person[_id].getPerson().equals("")){
System.out.println("Person " + _person[_id].getPerson() + " already exists.");
}else{
System.out.println("Enter the name of the person");
Scanner addPerson = new Scanner(System.in);
personName = addPerson.next();
_person[_id].setPerson(personName);
}
}else{
System.out.println("Person is not old enough");
}
return _person;
}
And here is the method setPerson in my custom class which is used to set the name of the person.
public void setPerson(String name){
System.out.println("Person added");
personName = name;
}
I know I should be doing the checking on whether that person already exists inside my setPerson method, but I am sort of confused with this. As you see I am expecting the user to input an integer, so I guess that I should check that right away to not get an error in case he inputs a string.
So my question is which should be checked within the same method and which on the method on my custom class?
Your code (and your question) is a bit confusing, but from what I can understand you want to know if you should check whether a person exists in the array in setPerson() or not?
Well, from what I can gather from your code, you should not do it in setPerson(), because that's a method in the Person class. The Person class shouldn't need to know anything about your array of Person objects.
So the way you're doing it now is probably your best bet.
Some general hints about the code:
There's no need to create a new Scanner, you can just use the one you have. So this
Scanner addPerson = new Scanner(System.in);
personName = addPerson.next();
becomes this
personName = scan.next();
I would also suggest you use the name setName()instead of setPerson()for your method name, it doesn't make sense to have it named one way when what it's actually doing is something else.
I would do it this way. However I don't have java currently so I didn't test this snippet.
class Person {
private String name;
public void setName(String name) {
this.name = name;
}
}
class Main {
private static final int minAge = 22;
private static Map<Person> addPerson(Map<Person> people, int id) {
if(people.containsKey(id)) {
// print that person with this id exists
return people;
}
Scanner scanner = new Scanner(System.in);
int age = scanner.nextInt();
if(age < minAge) {
// print that given age is invalid
return people;
}
String name = scanner.next();
people.get(id).setName(name);
return people;
}
}

Adding to an ArrayList using a TUI

I'm implementing a class called "BorrowerTUI" to an existing project for an assignment. I've been trying for hours and I just can't work out how to add to my ArrayList using the TUI. The information that needs to be added is in a class called "Borrower". Here is the constructor:
public Borrower(String fName, String lName, String lNumber, int numberOfBooks,
String street, String town, String postcode)
{
firstName = fName;
lastName = lName;
libraryNumber = lNumber;
noOfBooks = numberOfBooks;
address = new Address(street, town, postcode);
}
Previously, I added the object to the ArrayList using a different class called "BorrowerList". Here is the method:
public void addBorrower(Borrower borrower)
{
borrowers.add(borrower);
}
That works with no problems. Now what I'm trying to do is use a TUI to add the same information to the same ArrayList. Here is the constructor for "BorrowerTUI" and the options the user will have:
private BorrowerList borrowerList;
private Scanner myScanner;
public BorrowerTUI()
{
myScanner = new Scanner (System.in);
borrowerList = new BorrowerList();
Borrower borrower;
}
private void displayMenu()
{
System.out.println("To add a borrower........................[1]");
System.out.println("To get the total number of borrowers.....[2]");
System.out.println("To remove a borrower.....................[3]");
System.out.println("To show all borrowers....................[4]");
System.out.println("To show a single borrower................[5]");
System.out.println("To close Borrowers.......................[0]");
}
private void addBorrower()
{
borrowerList.addBorrower();
}
That doesn't work and I have tried to implement other solutions with no joy. I tried something along the lines of:
private void addBorrower()
{
myScanner = new Scanner(System.in);
String firstName;
String lastName;
borrower = (firstName, lastName);
System.out.println("Enter your first name: ");
myScanner.nextLine() = firstName;
System.out.println("Enter your last name: ");
myScanner.nextLine() = lastName;
borrowerList.add(borrower);
}
That was a bit of guess work as we haven't actually covered this material in class, we're expected to work it out ourselves having briefly touched on TUIs. Hopefully this is enough information, please let me know if you need me to elaborate or provide any additional code.

Using multiple constructors with one object in Java

I have two constructors for Student and am trying to use both of them with one object. But I should be doing it wrong because my output is not what I expect it to be.
Output:
School: null
Grade Level: 0
Intended Major: null
Student's ID number is: 154324
Student's name: Sam Bay
Student's GPA: 3.56
Code for class definition:
public class Student
{
private int id, gradeLevel;
private String name, school, major;
private double gpa;
//constructor to initialize the instance variables of student object
public Student(int id, String name, double gpa)
{
this.id = id;
this.name = name;
this.gpa = gpa;
}
public Student(int gradeLevel, String school, String major)
{
this.gradeLevel = gradeLevel;
this.school = school;
this.major = major;
}
//toString() to display the attributions of the student object
public String toString()
{
return "School: " + school +
"\nGrade Level: " + gradeLevel +
"\nIntended Major: " + major + "\n" +
"\nStudent's ID number is: " + id +
"\nStudent's name: " + name +
"\nStudent's GPA: " + gpa;
}
}//end class
code for main:
public class StudentDrive
{
public static void main(String [] args)
{
//creating student objects
Student sam = new Student(12, "Alpha High School", "Biology");
sam = new Student(154324, "Sam Bay", 3.56);
System.out.println(sam);
}
}
It seems like I've initialized the first part but I get null and 0??!!!
You can't use two constructors simultaneously on a single object.
In your code:
Student sam = new Student(12, "Alpha High School", "Biology");
creates a new Student object and assigns its reference to the variable sam.
On your next line:
sam = new Student(154324, "Sam Bay", 3.56);
This creates another Student object, separate from the first, and reassigns sam to refer to it instead. In the process, you end up orphaning the original Student and leave it open to garbage collection.
What you really want to do is either pass all data required for by a Student through a single constructor, or provide getters/setters (e.g. setGradeLevel(int level)) and a layer of exceptions that prevent methods from accessing a Student object until all fields are filled. The first option is generally more sound.
For example, a complete constructor would look something like this (formatted for readability):
public Student(int id, int gradeLevel, String name,
String school, String major, double gpa)
{
// fill your fields in here
}
I think you should read through the docs for a constructor again ;)
With Student sam = new Student(12, "Oakton High School", "Biology");
you are creating a Student-object with the given parameters and storing it in the variable sam.
When you call sam = new Student(154324, "Sam Bay", 3.56); you are again creating a new Student-object and storing it in sam. You are not modifying the first object but rather discarding it and creating a new one.
You should try adding a method to your Student object like:
public void setAdditionalValues(int id, String name, double gpa){
this.id = id;
this.name = name;
this.gpa = gpa;
}
Hope this is helpful :)
EDIT: as mentioned earlier you could also use one constructor that takes all the arguments or implement setters for each attribute of the Student-object like this:
public void setName(String name){
this.name = name;
}

How to load an ArrayList with instances of an Object I created

NOTE: I edited my code to how I think people are trying to tell me but it still doesn't give me my desired output. Now my output is "examples.search.Person#55acc1c2" however many times I enter new first and last names. At least it's making it through the code with out crashing lol
I am learning how to use ArrayLists and need to load an Array list with instances of an Object I created. I know how to do this with an array but for this assignment I need to do it with an ArrayList. Here's an example of what I need to do.
// my "main" class
package examples.search;
import java.util.ArrayList;
import dmit104.Util;
public class MyPeople {
public static void main(String[] args) {
ArrayList<Person> people = new ArrayList<Person>();
Person tempPerson = new Person();
String firstName;
String lastName;
char choice = 'y';
int count = 1;
// fill my ArrayList
do {
people.add(tempPerson);
// I have a Util class that has a prompt method in it
firstName = Util.prompt("Enter First Name: ");
lastName = Util.prompt("Enter Last Name: ");
tempPerson.setFirstName(firstName);
tempPerson.setLastName(lastName);
count++;
choice = Util.prompt(
"Enter another person? [y or n]: ")
.toLowerCase().charAt(0);
} while (choice == 'y');
// display my list of people
for(int i = 0; i < people.size(); i += 1) {
System.out.print(people.get(i));
}
}
}
// my Person class which I am trying to build from
public class Person {
// instance variables
private String firstName;
private String lastName;
// default constructor
public Person() {
}
public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
I've tried it a number of ways but no matter what my ArrayList doesn't fill up. Like I mentioned I can do it no problem with an array or even if I had a loaded constructor method but I don't. In my actual assignment I am supposed to do it with the set methods.
I have looked everywhere and cannot find the solution for my problem and being friday my instructor isn't in.
Thank you so much in advance
Leo
You'll have to create a Person and then add it to the ArrayList.
for (int i = 0; i < count; i++) {
Person person = new Person();
person.setFirstName("Foo");
person.setLastName("Bar");
people.add(person);
}
Its crashing because your line people.get(i).setFirstName(firstName); is first trying to what is at index i, but you have not set anything yet.
Either first set people[i] to a empty Person, or make a person using firstName and lastName, and add it to people using people.add(person);
You have an ArrayList<Person>, but that alone only defines a list of potential Person instances. But so far, each of the list entries is null. The get(i) returns null, and the following null.setFirstName(..) causes a NullPointerException.
So you need to create the instances of Person that are supposed to go into the list:
firstName = Util.prompt("Enter First Name: ");
Person p = new Person(); //create the instance
people.add(p); //add the instance to the list
p.setFirstName("..."); //set any values
Now you are storing the Person Object into an ArrayList and printing that Object.
To print the firstname and lastName when you print the Person object, you will have to override toString method.
Add the following code in your Person class
public String toString(){
return String.format("[Personn: firstName:%s ,lastName: %s]", firstName,lastName);
}
As for the second question you had, you have to override the toString() method in the Person class. The outputs you are getting, such as examples.search.Person#55acc1c2 is the default toString() method from the Object class, which is defined as class#hashCode

Trying To Output A String From An Object Passed Into A Set

I'm trying to output a string from an Object that has been passed into a set. The Following line is where my problem lies. It outputs [alex, jane] but with correct formatting I believe it should be outputted at alex jane. i.e. without the comma separated value and the brackets from the array.
System.out.print(module.getStudents() + " ");
I've tried various solutions including:
System.out.prinf(%s, module.getStudents() + " ");
and
System.out.prinln(module.getStudents().[whatever Netbeans makes available] + " ");
To help you better understand the problem. The idea of the application so far is to allow a user to search for a mosule ans return all students connected to it. The full source code bar the driver is:
import java.util.*;
public class Control {
public void run() {
Student jane = new Student("jane");
Student alex = new Student("alex");
Set<Student> students = new HashSet<Student>();
students.add(jane);
students.add(alex);
Module ufce1 = new Module("UFCE1");
Module ufce2 = new Module("UFCE2");
Set<Module> modules = new HashSet<Module>();
modules.add(ufce1);
modules.add(ufce2);
jane.addModule(ufce1);
jane.addModule(ufce2);
alex.addModule(ufce2);
ufce1.addStudent(jane);
ufce2.addStudent(jane);
ufce2.addStudent(alex);
System.out.println("Search module code: ");
Scanner scan = new Scanner(System.in);
scan = new Scanner(System.in);
String searchModule = scan.nextLine().trim();
for (Module module : modules) {
if (searchModule.equalsIgnoreCase(module.getName())) {
Iterator it = students.iterator();
Student student = (Student) it.next();
if (student.getModules().contains(module)) {
System.out.print(student + " ");
}
}
}
}
}
Module Class:
import java.util.HashSet;
import java.util.Set;
public class Module {
private String name;
private Set<Student> students = new HashSet<Student>();
public Module(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void addStudent(Student student){
students.add(student);
}
public Set<Student> getStudents() {
return students;
}
#Override
public String toString() {
return name;
}
}
Student Class:
import java.util.HashSet;
import java.util.Set;
public class Student {
private String name;
private Set<Module> modules = new HashSet<Module>();
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void addModule(Module module){
modules.add(module);
}
public Set<Module> getModules() {
return modules;
}
#Override
public String toString() {
return name;
}
}
When you do this System.out.print(module.getStudents() + " "); you're implicitly calling the toString method on the HashSet instance. So to get the formatting you want, you have 2 choices:
iterate over the set and print it the way you want
Subclass HashSet and override toString to display the way you want it.
The problem is that getStudents returns a Set object (a HashSet, to be specific). HashSet, in turn, inherits a toString() method from AbstractCollection which behaves as follows:
Returns a string representation of this collection. The string representation consists of a list of the collection's elements in the order they are returned by its iterator, enclosed in square brackets ("[]"). Adjacent elements are separated by the characters ", " (comma and space). Elements are converted to strings as by String.valueOf(Object).
You'll need to write your own method for converting a set of students into the format you want, or else you can doctor up the value returned by the default toString implementation.
The brackets and the commas are coming from the toString() call on the Set. If you look in the source code of this method, you will see that it adds those. You can override the toString() method of the Set in your Module class, or just not printing the Set directly but manually looping over all elements and printing them one by one
#Chris gave an excellent solution in resolving your issues. There is however another one that I see more easy to implement and it is the following:
public String formatOutputString(){
String setStrings = module.getStudents();
// Get rid of opening bracket
String formatedString = setStrings.replace("[", "");
// Get rid of closing bracket
formatedString = setStrings.replace("]", "");
// Replace commas by spaces
formatedString = setStrings.replace(",", " ");
return formatedString;
}

Categories