Best way to add objects' field to a list - java

So I have this GameType class:
public class GameType {
private final String name;
public GameType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
and I have a list of my game types, so, basically I want to print all of my GameType classes' name field and I am using Java 8, this is what I have done so far:
List<String> list = new ArrayList<>();
gameTypes.forEach(gameType -> list.add(gameType.getName()));
System.out.println(list);
So, what I am asking is, is there a better way to do that?

You can try this:
System.out.println(gameTypes.stream()
.map(GameType::getName)
.collect(Collectors.toList()));

Related

Collections.sort that accept multiple parameters

I am new to Java. I am learning about Java Collections and I have question about writing a program to sort by attributes. So I have a class Course with these variables:
public class Course{
private String courseName;
private String courseDescription;
}
And another class Student that contains class Course which is a linked list of Course variables:
public class Student{
private String name;
private LinkedList<Course> courses;
}
public Student(String name) {
this.name = name;
this.courses = new LinkedList<Course>();
}
I want to write a method public void sortCourse() { } in Student class that should accept parameters to specify whether the sorting should be ascending or descending and also based on which course attribute to sort the courses, and print the sorted list of course. How can I write this method?
As Fureeish said in a comment: Make it accept a Comparator.
Like this:
public void sortCourse(Comparator<Course> comparator) {
this.courses.sort(comparator);
}
The caller would then write something like this:
// Sort ascending by name
student.sortCourse(Comparator.comparing(Course::getCourseName));
// Sort decending by name
student.sortCourse(Comparator.comparing(Course::getCourseName).reversed());
// Sort ascending by course level, then description
student.sortCourse(Comparator.comparing(Course::getCourseLevel)
.thenComparing(Course::getCourseDescription));
You can use Comparable interface to sort the courses. For that your Course class need to implements the Comparable interface.
public class Course implements Comparable <Course>{
private String courseName;
private String courseDescription;
public Course(String courseName, String courseDescription){
this.courseName = courseName;
this.courseDescription = courseDescription;
}
public int compareTo(Course c) {
return this.courseName.compareTo(c.courseName);
}
}
Now you can call Collections.sort(student.courses) method to sort the course list.
public class Student{
private String name;
private LinkedList<Course> courses;
public Student(String name) {
this.name = name;
this.courses = new LinkedList<Course>();
}
public void sortCourse(String sortOrder){
if(sortOrder.equals("asc")){
Collections.sort(this.courses);
} else {
Collections.sort(this.courses);
Collections.reverse(this.courses);
}
}
}

How can I permit an ArrayList from removing added objects without overriding or making it immutable

Guys I have created an ArrayList and I don't want to make it immutable. I just seek to find a solution as for how to not allow the ArrayList from removing the objects.
public final class EMailArchive {
private final String name;
private final ArrayList <EMail> emailList;
private final LocalDate date;
public EMailArchive(String name, ArrayList <EMail> emailList) {
this.name = name;
this.emailList = emailList;
date = LocalDate.now();
}
public String getName() {
return name;
}
public LocalDate getDate( ) {
return date;
}
public List <EMail> getEMailList() {
return emailList;
}
public void addEMailToArchive(final EMail mail) {
emailList.add(mail);
// the mail added to the list shall not be removed, but how do i do that
}
}
One way is to implement a subClass of ArrayList that override the remove method
class myArrayLit extends ArrayList {
public myArrayList() {
super();
}
#Override
public remove(int index) {}
}
This is a basic example, there are more method to override, to achieve your goal.
If the solution above with extending ArrayList is not appropriate for whatever reason, you could return a copy within the getter, like this:
public List <EMail> getEMailList() {
return new ArrayList<>(emailList);
}
Changes to the returned List will not be reflected back to the class member.

How to change array to an object class?

I have cut out the code to shorten the page but I'm asking how do I change personInterests into its own class. Apologies for the vague question but essentially I want to change personInterests in my Person class to a class where personInterests has multiple variables.
import java.util.ArrayList;
import java.util.*;
public class Person{
private String personName;
private String[] personInterests = new String[3];
public Person(String personName, String[] personInterests){
this.personName = personName;
this.personInterests = personInterests;
}
public void setInterests(String[] personInterests){
this.personInterests = personInterests;
}
public String[] getInterests(){
return personInterests;
}
public String getName(){
return personName;
}
public String toString(){
String result = getName() + " ";
for (String interests : personInterests) {
result += interests + " ";
}
return result;
}
}
This was my idea of how it would work just not sure how I would use this class and call it later on.
import java.util.ArrayList;
import java.util.*;
public class Interests {
private int interestDangerRating;
private String interestName;
private ArrayList<Interests> interestsList = new ArrayList<>();
public Interests (int interestDangerRating ,String interestName){
this.interestDangerRating = interestDangerRating;
this.interestName = interestName;
}
public void addInterests(Interests p){
interestsList.add(p);
}
Interests getInterests(int i){
return interestsList.get(i);
}
}
Any help is appreciated, as I said this code has mostly been taken out and this was an old project already completed just wanted to see if I could change some of the features.
OK so here's what I would do to clean this up for you and make it work. Firstly, think about what you are trying to do. You want to create a Person who has multiple Interests, right? So the Interest class, going by your above example, can be changed to be a typical Java object class as follows:
public class Interest {
private int dangerRating;
private String name;
public Interest (int dangerRating, String name) {
this.dangerRating = dangerRating;
this.name = name;
}
public int getDangerRating() {
return dangerRating;
}
public String getName() {
return name;
}
}
So now we've an Interest class set up where you can set a name for your interest and a danger rating. What we need to do, now, is edit your Person class so as you can store a list of interests for each Person you create.
import java.util.ArrayList;
public class Person{
private String name;
private ArrayList<Interest> interests = new ArrayList<Interest>();
public Person(String name, ArrayList<Interest> interests) {
this.name = name;
this.interests = interests;
}
public void addInterest(Interest newInterest) {
interests.add(newInterest);
}
public Interest getInterest(int indexOfInterest) {
return interests.get(indexOfInterest);
}
public ArrayList<Interest> getInterests() {
return interests;
}
public String getName() {
return name;
}
public String toString() {
String result = getName() + " ";
for(Interest interest : interests) {
result += interest.getName() + "(" + interest.getDangerRating() + ")" + " ";
}
return result.trim();
}
}
This allows you to set an initial list of all interests for your new Person and, from there, you can add new interests, get all interests or get any individual interest.
Hope this helps to clarify for you how this should all fit together!
So now it's time to instantiate everything. Lets create some Interestobjects which we will use:
Interest golf = new Interest(1, "golf");
Interest swimming = new Interest(3, "swimming");
Now lets assume we want two people called John and Mary. John likes golf and swimming while Mary only likes swimming. We'd then create their list of Interest as follows:
ArrayList<Interest> johnsInterests = new ArrayList<Interest>();
johnsInterests.add(golf);
johnsInterests.add(swimming);
ArrayList<Interest> marysInterests = new ArrayList<Interest>();
marysInterests.add(swimming);
And finally, we'd then create our two Person objects which will include the persons name and interests list.
Person john = new Person("John", johnsInterests);
Person mary = new Person("Mary", marysInterests);
And voila!
First, make an Interestclass:
public class Interest {
private int interestDangerRating;
private String interestName;
// .. getters and setters
}
then in the Personclass get rid of private String[] personInterests = new String[3];
and replace it by:
private ArrayList<Interest> interestsList = new ArrayList<>();
You're getting there with the logic of your Interests class, but it needs a few changes
import java.util.ArrayList;
import java.util.*;
public class Interests {
private int interestDangerRating;
// Is this a unique name for the entire class? If yes then no worries, but if not
// then its not needed, you've already got a list of interest names below
private String interestName;
// Change the array list to hold Strings, it's a list of words
private ArrayList<String> interestsList = new ArrayList<>();
public Interests (int interestDangerRating ,String interestName){
this.interestDangerRating = interestDangerRating;
this.interestName = interestName;
}
public void addInterest(String p){ // Again, change this to String
interestsList.add(p);
}
String getInterest(int i){ // Change this to return a String, since we changed the ArrayList above
return interestsList.get(i);
}
}
There's alot more you need to think about with this class too. How do you know how many interests are in the list, should there be a length variable? Or what about a method that returns the entire list of interests rather than just 1?
Also, there's only one interestDangerRating being set in this class; if each interest has a different danger rating, should't you be adding a danger rating for every interest?
In terms of accessing your new class, you'll need to create a class in your code by:
Interests variableName = new Interests(1, "football");
I have randomly chosen '1' and 'football' above, since they are in your Interest class' constructor. The way your class is built, you cannot use it without providing an int and a String when the object is made
Finally, to call methods on your class, you use the variable created above to call its methods:
variableName.addInterest("basketball");
String interest = variableName.getInterest(1);
If you're struggling, I recommend looking at a simple java tutorial online. instatiating java classes and calling their methods like this are fundamental concepts in Java :)

How can I extract values from a list of objects based on a property of these objects?

I'd like to find objects in a list based on having a certain property.
For example, say I have a list of objects of this class:
class Person {
private String name;
private String id;
}
I know that I can get all of the names of people in the list by using:
Collection<String> names = CollectionUtils.collect(
personList,
TransformerUtils.invokerTransformer("getName"));
but what I want to do is get a list of the Person objects whose name is, for example, "Nick". I don't have Java 8.
I see you are using Apache Common Utils, then you can use:
CollectionUtils.filter( personList, new Predicate<Person>() {
#Override
public boolean evaluate( Person p ) {
return p.getName() != null && p.getName().equals( "Nick" );
}
});
If you don't want to use Java 8 streams, simply loop through the list and check the elements manually:
ArrayList<Person> filteredList = new ArrayList<Person>();
for(Person person : personList) {
if(person.getName().equals("Nick")) filteredList.add(person);
}
Using Apache collection utils (which you are already using), you can use the filter method which creates a subset of your collection consisting of items which match a given filter, combined with a Predicate that matches "Nick" based on your Transformer and transformedPredicate:
CollectionUtils.filter(names, PredicateUtils.transformedPredicate(
TransformerUtils.invokerTransformer("getName"), PredicateUtils.equalPredicate("Nick")));
That said, you may want to reconsider using such a heavily functional approach before you migrate to Java 8. Not only will you have a lot of redundant Apache collections code after you migrate, the solutions prior to the introduction of closures and lambdas tend to be verbose and often less readable than the imperative alternatives.
Note: this modifies the existing collection in-place. If that is not the desired behavior, you'll need to create a copy before calling the filter method.
You could try using a HashMap.
HashMap<String, Integer> points = new HashMap<String, Integer>();
points.put("Amy", 154);
points.put("Dave", 42);
points.put("Rob", 733);
System.out.println(points.get("Dave"));
This would only be an example, but you could check and instead of having the String, Integer, you could try Integer, String and have an if statement. Just an idea though.
I am considering that you might have a collection of different objects that have this property name. For that I would recommend you to do parent for those components and perform the search on it with generics:
For example:
Parent class Name.java
public class Name {
private String name;
public Name(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Class Pet.java
public class Pet extends Name{
public Pet(String name) {
super(name);
}
}
And class Person.java
public class Person extends Name{
public Person(String name) {
super(name);
}
}
Job class that doesn't have the property:
public class Job {
private String description;
public Job(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Having that, you can check the instance of it and compare what you want:
public static void main(String ... args) {
List<Object> objectList = new ArrayList();
objectList.add(new Person("Nick"));
objectList.add(new Person("Nik"));
objectList.add(new Person("Nikc"));
objectList.add(new Person("Ncik"));
objectList.add(new Pet("Nick"));
objectList.add(new Pet("Nik"));
objectList.add(new Pet("Nikc"));
objectList.add(new Pet("Ncik"));
objectList.add(new Job("Nick"));
objectList.add(new Job("Nik"));
objectList.add(new Job("Nikc"));
objectList.add(new Job("Ncik"));
for (Object o : extractObjectsMatching("Nick", objectList)){
System.out.println(((Name) o).getName());
}
}
public static List<Object> extractObjectsMatching(String name, List<Object> objectList){
List<Object> matches = new ArrayList<>();
for (Object e : objectList){
if (e instanceof Name && ((Name) e).getName().contains(name)){
matches.add(e);
}
}
return matches;
}
If the Object class is not an instance of Name, means that will not have the property that you are looking for, just ignore, otherwise, compare with the information that you want and store to retrieve.

String Array object in Java

I am trying to print the first element on the two arrays in my Athlete class, country and name. I also need to create a object that simulates three dive attemps an athlete had (that is initially set to zero). I am new to OOP and I dont know how to go abouts doing this in my main... as far as constructors go. This is what i have done so far...
this is the main:
import java.util.Random;
import java.util.List;
public class Assignment1 {
public static void main(String[] args) {
Athlete art = new Athlete(name[0], country[0], performance[0]);
}
}
I just really am not sure what to do...
And this is the class with the arrays.
import java.util.Random;
import java.util.List;
public class Athlete {
public String[] name = {"Art", "Dan", "Jen"};
public String[] country = {"Canada", "Germant", "USA"};
//Here i would like to create something that would be representing 3 dive attemps (that relate to dive and score. eventually.)
Athlete(String[] name, String[] country, Performance[] performance) {
this.name = name;
this.country=country;
this.performance=performance;
}
public Performance Perform(Dive dive){
dive.getDiveName();
return null;
}
public String[] getName() {
return name;
}
public void setName(String[] name) {
this.name = name;
}
public String[] getCountry() {
return country;
}
public void setCountry(String[] country) {
this.country = country;
}
}
thanks in advance for any help and input!
btw there is other classes too, just not relevant atm..
First, as for your Athlete class, you can remove your Getter and Setter methods since you have declared your instance variables with an access modifier of public. You can access the variables via <ClassName>.<variableName>.
However, if you really want to use that Getter and Setter, change the public modifier to private instead.
Second, for the constructor, you're trying to do a simple technique called shadowing. Shadowing is when you have a method having a parameter with the same name as the declared variable. This is an example of shadowing:
----------Shadowing sample----------
You have the following class:
public String name;
public Person(String name){
this.name = name; // This is Shadowing
}
In your main method for example, you instantiate the Person class as follow:
Person person = new Person("theolc");
Variable name will be equal to "theolc".
----------End of shadowing----------
Let's go back to your question, if you just want to print the first element with your current code, you may remove the Getter and Setter. Remove your parameters on your constructor.
public class Athlete {
public String[] name = {"Art", "Dan", "Jen"};
public String[] country = {"Canada", "Germany", "USA"};
public Athlete() {
}
In your main method, you could do this.
public static void main(String[] args) {
Athlete art = new Athlete();
System.out.println(art.name[0]);
System.out.println(art.country[0]);
}
}
Currently you can't access the arrays named name and country, because they are member variables of your Athelete class.
Based on what it looks like you're trying to do, this will not work.
These arrays belong in your main class.
Your attempt at an athlete class seems to be dealing with a group of athletes, which is a design fault.
Define a class to represent a single athlete, with fields that represent the athlete's attributes:
public class Athlete {
private final String name;
private final String country;
private List<Performance> performances = new ArrayList<Performance>();
// other fields as required
public Athlete (String name, String country) {
this.name = name;
this.country = country;
}
// getters omitted
public List<Performance> getPerformances() {
return performances;
}
public Performance perform(Dive dive) {
// not sure what your intention is here, but something like this:
Performance p = new Performance(dive, this);
// add new performance to list
performances.add(p);
return p;
}
}
Then your main method would use ti like this:
public class Assignment1 {
public static void main(String[] args) {
String[] name = {"Art", "Dan", "Jen"};
String[] country = {"Canada", "Germant", "USA"};
Dive[] dive = new Dive[]{new Dive("somersault"), new Dive("foo"), new Dive("bar")};
for (int i = 0; i < name.length; i++) {
Athlete athlete = new Athlete(name[i], country[i]);
Performance performance = athlete.perform(dive[i]);
// do something with athlete and/or performance
}
}
}
I think you are a little messed up with what you doing.
Athlete is an object, athlete has a name, i has a city where he lives.
Athlete can dive.
public class Athlete {
private String name;
private String city;
public Athlete (String name, String city){
this.name = name;
this.city = city;
}
--create method dive, (i am not sure what exactly i has to do)
public void dive (){}
}
public class Main{
public static void main (String [] args){
String name = in.next(); //enter name from keyboad
String city = in.next(); //enter city form keybord
--create a new object athlete and pass paramenters name and city into the object
Athlete a = new Athlete (name, city);
}
}
public static void main(String[] args) {
public String[] name = {"Art", "Dan", "Jen"};
public String[] country = {"Canada", "Germant", "USA"};
// initialize your performance array here too.
//Your constructor takes arrays as an argument so you need to be sure to pass in the arrays and not just objects.
Athlete art = new Athlete(name, country, performance);
}
First off, the arrays are pointless, let's get rid of them: all they are doing is providing values for mock data. How you construct mock objects has been debated ad nauseum, but clearly, the code to create the fake Athletes should be inside of a unit test. I would use Joshua Bloch's static builder for the Athlete class, but you only have two attributes right now, so just pass those in a Constructor. Would look like this:
class Athlete {
private String name;
private String country;
private List<Dive> dives;
public Athlete(String name, String country){
this.name = name;
this.country = country;
}
public String getName(){
return this.name;
}
public String getCountry(){
return this.country;
}
public String getDives(){
return this.dives;
}
public void addDive(Dive dive){
this.dives.add(dive);
}
}
Then for the Dive class:
class Dive {
private Athlete athlete;
private Date date;
private double score;
public Dive(Athlete athlete, double score){
this.athlete = athlete;
this.score = score;
this.date = new Date();
}
public Athlete getAthlete(){
return this.athlete;
}
public Athlete getAthlete(){
return this.athlete;
}
public Athlete getAthlete(){
return this.athlete;
}
}
Then make a unit test and just construct the classes, and manipulate them, make sure that they are working. Right now they don't do anything so all you could do is assert that they are retaining the Dives that you are putting in them. Example:
#Test
public void testThatDivesRetainInformation(){
Athlete art = new Athlete("Art", "Canada");
Dive art1 = new Dive(art, 8.5);
Dive art2 = new Dive(art, 8.0);
Dive art3 = new Dive(art, 8.8);
Dive art4 = new Dive(art, 9.2);
assertThat(art.getDives().size(), is(5));
}
Then you could go through and add tests for things like, making sure that you can't construct a dive without an athlete, etc.
You could move construction of the athletes into the setup method of the test so you could use it all over the place. Most IDEs have support for doing that with a refactoring.

Categories