Updating ArrayLists that contains each other? - java

Apologies if there have been similar questions, I'm honestly not sure how to call this concept to search for questions.
So I need to create a database with 3 classes like below:
public class Actor {
private String name;
private ArrayList<Movie> movies; //all movies the actor has been in
}
public class Movie {
private String name;
private ArrayList<Actor> actors;
}
public class MovieDatabase {
private ArrayList<Movie> movieList;
private ArrayList<Actor> actorList; //all actors in the movie
}
I have to create a method to add a movie and an actor to the database.
The final goals is that the new movie needs to be of the Movie class, and contains all the actors that are in it, same for the new actor.
What I cannot figure out is that, since the Movie class contains an array of Actor objects, and the Actor class contains an array of Movie list, how do you update so that in the end, the new Movie added contains a complete list of Actors in it, with each Actor in the list having their movie lists updated with the new Movie object?
Is recursion the right concept to apply in this case?

Suppose a new Movie gets added
Movie movie = new Movies();
movie.setActors(listOfActors)
Now for each actor you need to update the movie list
listOfActors.forEach(actor -> addMovieToActor(movie,actor));
public addMovieToActor(Movie movie,Actor actor){
List<Movies> existingMovies =actor.getMovies();
existingMovies.add(movie);
}
Depending on your needs, you may need to take care of synchronization between updates.

I don't think recursion is appropriate here, although you could use it. The databases have a circular dependency so you just need to synchronize after updates. In other words, make sure that after you add a new entry, both databases are updated with the missing information. Synchronization can be made easier by swapping ArrayList out for a HashMap, you may need to refactor your classes to do this. I left out the lists for simplicity, you can add them in as a parameter:
void update(String movieName, String actorName) {
if (movies.get(movieName) == null) {
movies.put(movieName);
}
if (actors.get(actorName) == null) {
actors.put(actorName);
}
}
Use as:
HashMap<String> actors = new HashMap<>();
HashMap<String> movies = new HashMap<>();
actors.put("foo");
movies.put("bar");
// Update happened, synchronize with what you just added
update("foo", "bar");

Related

Java - Android How to return a List from a Class to multiple Classes?

I'm trying to create a reusable Class on Android that fetches Users data from a Firebase Database, creates a list of Users Models, and returns that list to any other classes that might need the list. But I'm not being able to do it. I won't bother you with all the code, but what I got is basically this:
Class Reusable {
//declare FireBase Auth, DatabaseReference, etc.
private Context mContext;
private List<Users> mUserList;
public Reusable (Context context){
mContext = context;
mUserList= new ArrayList<>();
}
}
public void getUsersIdFromDb(){
List<Strings> idList = = new ArrayList<>();
//gets Users Id from Database and save it to idList:
idList.addAll(ids); //ids are ids fetched from Database
Log.d("StepOne",Integer.toString(idList.size(); //returns correct number of ids
createListOfModels(idList);
}
private void createListOfModels(final List<Strings> list){
//compares fetched ids with ids inside logged user node
//if it passes:
for(String id: list){
String name = datasnapshot.child(id).child("name).getValue();
String pic= datasnapshot.child(id).child("pic).getValue();
UserModel user = new UserModel(name, pic);
mUserList.add(user);
}
processListOfUsers(mUserList);
}
private void processListOfUsers(List<Users> list){
for (User u: list){
mUserList.add(u);
Set<Users> hs = new LinkedHashSet<>();
hs.addAll(mUserList);
mUserList.clear();
mUserList.addAll(hs);
Log.d("StepThree",Integer.toString(mUserList.size(); //returns correct number of Users
}
}
public List<Users> getList(){
return mUserList;
}
Then, when calling the Reusable class:
public SomeClass extends AppCompatActivity {
//onCreate, etc...
Reusable reusable = new Reusable(SomeClass.this);
reusable.getUsersIdFromDb();
int i = reusable.getList().size();
Log.d("FromSomeClass", Integer.toString(i);
//returns 0 when it should return the size of the List from Reusable;
//How do I get the List From Reusable Class??
}
As you can see from the size of the list at the Log, it is returning an empty list. How should I set Reusable, so that it returns the list when other classes call?
I'm still finding my way through Java and Android, so I'd appreciate your help.
[EDIT] Maybe it has something to do with the fact that Firebase calls are Asynchronous? Because, you see, as long as I'm passing the results to the parameters, the Logs return a full List. But calling a method outside this chain, perhaps triggers its execution outside the Firebase thread, where the list is still empty.
I didn't quite get what the problem is you're trying to solve. If it is the fact that it returns zero then that's because you never fill the list with anything in this code. The list exists, it's just empty.
The Constructor creates an empty list (size 0)
public Reusable (Context context){
mContext = context;
mUserList= new ArrayList<>();
}
Then you actually DO get the list.
First you create a new reusable which creates an empty list inside it
Reusable reusable = new Reusable(SomeClass.this);
Then you get the size of that list which is zero
int i = reusable.getList().size();
There isn't an error here, you just need to fill the list in the constructor or somewhere.

Accessing and using custom Objects and ArrayList<Object> in different methods

I am currently working on an app that will use many objects as information holders (music things - artist, song, id of album cover img, and another id of 2nd img).
I decided that it would be the best to create "Track" class and use it to make objects and store them in ArrayList.
I created the class, I created the list, but I'm having trouble with accessing it (I want to change the ImageViews and TextViews basing on current Track object).
Here's the Track Class: (Track.java separate)
public class Track {
private String mNameArtist;
private String mNameTrack;
private int mTabResource;
private int mCoverResource;
public Track(String nameArtist, String nameTrack, int tabResourceId, int coverResourceId){
mNameArtist = nameArtist;
mNameTrack = nameTrack;
mTabResource = tabResourceId;
mCoverResource = coverResourceId;
}
public String getArtistName() {
return mNameArtist;
}
public String getTrackName() {
return mNameTrack;
}
public int getTabResourceId() {
return mTabResource;
}
public int getCoverResourceID() {
return mCoverResource;
}}
And here's ArrayList declaration: (PlayActivity.java, inside onCreate method)
ArrayList<Track> Tracks = new ArrayList<Track>();
Tracks.add(new Track("Artist Name", "Track Name", R.drawable.tabtemplate, R.drawable.testcover));
Tracks.add(new Track("Pink Floyd", "Comfortably Numb Solo 1", R.drawable.CNS1Tab, R.drawable.pink_floyd_the_wall));
There are more positions, but you get the idea.
Everything seems to work fine up to this point.
When I want to access it inside another method (even in the same PlayActivity.java) nothing happens or I see errors. I tried many different approaches but every single one fails. For example:
Track.getTabResource(); // can't even use the method.
Tracks.get(3); // does not work as well.
I just can not use objects or that arraylist inside my methods. The "Tracks array" won't even show up in Android Studio when typing. Track does, but I can't access positions from Array.
So to sum up, is there any other way I can use my Objects (ArrayList) items inside other classes and methods?
Thank you for your help in advance.
Create List as instance variable and access through Object of that class.
public class PlayActivity {
List<Track> tracks = new ArrayList<Track>();
public void onCreate() {
tracks.add(new Track("Artist Name", "Track Name", R.drawable.tabtemplate, R.drawable.testcover));
tracks.add(
new Track("Pink Floyd", "Comfortably Numb Solo 1", R.drawable.CNS1Tab, R.drawable.pink_floyd_the_wall));
}
public List<Track> getAllTracks() {
return Collections.unmodifiableList(tracks);
}
public Track getTrack(int index) {
return tracks.get(index);
}
}

Java object extensions

So i'm in the process of building a movie hiring system and have come to conclusion that I want to have a class of movies (which have specific movie data stored) and then another class which will have objects which extend the specific movies (eg, copies of Star wars: the new Hope) each with their own unique ID.
How do I setup my classes so that the information for each unique movie is inherited by the copy objects? (will extending my movieCopy class by my movies class achieve what I'm trying to do? Because I was thinking that would just extend the variables of the movie class, rather than the specific attributes of each object of the movie class.
Sorry in advance for any communication errors. Please feel free to ask if you need me to clarify something.
Structure I'm trying to achieve:
Movie (class)
MovieCopy(class)
MovieCopy <- attributes of the specific movie are inherited in each copy of the movie
Your MovieCopy class (DVD, Bluray, ...) could just contain a member variable storing the associated Movie instance (actual film with title, description, ...). That way you have access to all the meta data without any awkward inheritance.
class Movie {
private long id;
private String title;
private LocalDate release;
private String contentDescription;
Movie(long id, String title) {
this.id = id;
this.title = title;
}
...
}
class MovieCopy {
private long copyId;
private Movie movie;
private LocalDate lastHired;
private LocalDate latestReturn;
MovieCopy(long id, Movie movie) {
this.copyId = id;
this.move = movie;
}
...
}
EDIT - You would populate your collection of movies like this:
Movie starWars4 = new Movie(1, "Star Wars 4");
MovieCopy starWarsDvd1 = new MovieCopy(1, starWars4);
MovieCopy starWarsDvd2 = new MovieCopy(2, starWars4);
MovieCopy starWarsDvd3 = new MovieCopy(3, starWars4);
As a result you have three copies of the same Movie.
In your case, inheritance is not very suitable. What you are trying to do is create objects. You don't even need a MovieCopy class. You store the specific details of each movie in the movie objects.
Let's assume that your movie class has a name and a durationInMinutes fields and they both have getters and setters. If you want to create a new movie copy, you can do this:
Movie movie = new Movie ();
movie.setName("Star Wars");
movie.setDurationInMinutes (150);
And then you can refer to Star Wars using the variable name --- movie.
You might have other fields in your Movie class but you get the idea, right?
Let me show you when to use inheritance: if you have a kind of movie that has some attributes that ordinary movies don't have, which I can't give you an example because there is only one kind of movie.

How to design objects for simple school application [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I want to create simple school application that provides grades,notes,presence,etc. for students,teachers and parents. I'm trying to design objects for this problem and I'm little bit confused - because I'm not very experienced in class designing. Some of my present objects are :
class PersonalData() {
private String name;
private String surename;
private Calendar dateOfBirth;
[...]
}
class Person {
private PersonalData personalData;
}
class User extends Person {
private String login;
private char[] password;
}
class Student extends Person {
private ArrayList<Counselor> counselors = new ArrayList<>();
}
class Counselor extends Person {
private ArrayList<Student> children = new ArrayList<>();
}
class Teacher extends Person {
private ArrayList<ChoolClass> schoolClasses = new ArrayList<>();
private ArrayList<Subject> subjects = new ArrayList<>();
}
This is of course a general idea. But I'm sure it's not the best way. For example I want that one person could be a Teacher and also a Parent(Counselor) and present approach makes me to have two Person objects. I want that user after successful logging in get all roles that it has (Student or Teacher or (Teacher & Parent) ). I think I should make and use some interfaces but I'm not sure how to do this right. Maybe like this:
interface Role {
}
interface TeacherRole implements Role {
void addGrade( Student student, Grade grade, [...] );
}
class Teacher implements TeacherRole {
private Person person;
[...]
}
class User extends Person{
ArrayList<Role> roles = new ArrayList<>();
}
Please if anyone could help me to make this right or maybe just point me to some literature/article that covers practical objects design.
In a system like this, it seems like you can create a User class that has all the personal properties as well as account information in it:
public class User
{
// personal properties
private String name;
private String surname;
private Calendar dateOfBirth;
// account properties;
private String login;
private String password; // note that string may be more convenient than char[]
// role properties
public ArrayList<Role> roles;
...
public bool hasRole(Role role) // or isInRole(Role role)
{ // implementation here. }
}
Then you have your Role object:
public class Role
{
private String name;
private String description;
}
Note that there is only one role class that could be any of teacher, student, parent, etc. Since the Role class is generic, we do not have functions in it such as addGrade(), since that is specific to a teacher.
When the user logs in with proper credentials, such a system would already know the roles associated with the user. Usually, role-specific tabs, links, and other UI elements would show (or not show) depending on the role. This is where you check to see if the user logged in is in a particular role (user.hasRole(...)). For each UI element whose visibility is determined by the role, you would have to have an if (user.hasRole(...)).
In regard to the composition issues, this system is one that heavily relies on relationship between objects. Let's consider the relationship between students and counselors - a counselor has students assigned to him/her. Likewise, any given student has many counselors. You've got a many-many relationship which calls for a structure that keeps track of the combination of unique student-counselor pairs:
public class StudentCounselor
{
public User student;
public User counselor;
}
And who keeps track of all of this? Most likely the system itself, not another user.
public class SystemAdministration
{
public static ArrayList<StudentCounselor> studentCounselors = new ArrayList<StudentCounselor>();
public static void addStudentCounselor(User student, User counselor)
{
// Check to see first that the student-counselor combo doesn't exist
studentCounselors.addItem(student, counselor);
// addItem may not be the precise name of the function in ArrayList.
}
// function to obtain all students of a counselor
public static ArrayList<User> getStudentsOfCounselor(User counselor)
{
// iterate through the studentCounselors ArrayList and pick only
// the Student-Counselor whose counselor is the same counselor
// as the one passed into this function.
// Then extract the student property out of the fitting
// Student-Counselor.
// Return the list of students.
}
public static ArrayList<User> getCounselorsOfStudent(User student)
{
// Similar as above, but the other way around.
}
}
You would do similar for your other relationships - parent-student, teacher-sections, etc. The SystemAdministration class is NOT a role, but the entity responsible for providing you with all the data.
As a suggestion, consider the Section object:
public class Section
{
public User teacher; // who teaches it
public Course course; // what is the subject, because > 1 teacher might teach the same one.
public TimeBlock timeBlock; // when is this section administered?
public Venue venue; // what room or what facility
}
You would have to create the TimeBlock and Venue classes. This structure, when put in an ArrayList will be able to answer the questions: "As a teacher, what sections will I teach?" and that answers the question "what subjects, when, and where will I teach them?"
As for the student, you'll need the StudentSection "combo" class:
public class StudentSection
{
public Section section;
public User student;
}
When put in an ArrayList of the SystemAdministrator class, now you can iterate through the list to extract what sections are assigned to a student (aka, the student's schedule), and likewise, who are the students of a given section.
Note that we don't have a list of related items in the User class except roles. To obtain any data, info about the logged-in user and his/her roles should be sufficient as long as you have all the data and access functions in a global (in this case SystemAdministration) structure.
There is no "right" design; it all depends on how you plan to interact with these classes/interfaces. Try to sketch the methods you intend to call, in the most natural possible way, and work from those to understand what a good layout for your classes could be. If you feel brave, try learning the Test Driven Development methodology; writing actual unit tests before the "real" code can help make your mind on the class structures.
As a general suggestion, try to avoid inheritance, and favor composition instead. Having an array of Role elements is a step towards that direction; try to understand you plan to interact with these roles, and add methods accordingly.

java data-structure to simulate a data tree

I need help defining what approach to use. I have a SOAP response giving me an xml file. I need to end-up with 3 correlated lists displayed on screen. When you select one item on the first list, the corresponding choices will appear on the second list etc. I am only interested on how to organize efficiently the data after it is extracted from the xml stream. Here's an xml snippet:
<device>
<manufacturer>Acer</manufacturer>
<model>A1</model>
<platform>Android</platform>
</device>
<device>
<manufacturer>Acer</manufacturer>
<model>A1</model>
<platform>J2ME</platform>
</device>
<device>
<manufacturer>Acer</manufacturer>
<model>A2</model>
<platform>Android</platform>
</device>
<device>
<manufacturer>Samsung</manufacturer>
<model>E400</model>
<platform>Android</platform>
</device>
So, I will have something like manufacturer={"Acer", "Acer", "Acer","Samsung"}, model={"A1","A1", "A2", "E400"}, platform={"Android","J2ME","Android","Android"}.
Here comes the fun part: I need to massage the data so that I can use it to display 3 lists. After selecting Android, Acer and Samsung become available. If Acer is selected, then model A1 and A2 are available. All lists need to be sorted. Currently I'm using Sax to parse the data into a vector of objects, containing manufacturer, model, platform fields. All I can think of is a TreeMap like structure. Any suggestions would be appreciated.
I do not think that hierarchical structure is what you need here. Because user may select first platform or manufacturer. If he selects first Android you want to show 3 devices. If he selects first Acer he will see 2 devices.
So, my suggesting is the following.
create class Device with properties manufacturer, model, platform.
create a plain linked list that contains all these devices.
Create 2 maps: manufaturerIndex and plarformIndex that look like:
Map<String, Collection<Device>> manufacturerIndex;
Iterate once over the list and populate all indexes maps.
Like this:
for(Device d : devices) {
Collection<Device> selected = manufacturerIndex.get(d.getManufacturer());
if (selected == null) {
selected = new ArrayList<Device>();
manufactuerIndex.put(d.getManufacturer(), selected);
}
selected.add(d);
// the same for the second index
}
Now you can use the data structure.
manufactuerIndex.get("Nokia") -> returns all Nokia devices.
Pay attention that this data structure is extendable. You can always add as many indexes as you want.
I'd just use a sortable collection of custom objects and then filter that collection based on predicates. I am using Guava for all of this, but there are of course other (usually more complicated) ways to implement this.
Here's my Product Object:
public class Product implements Comparable<Product>{
private final String manufacturer;
private final String model;
private final String platform;
public Product(final String manufacturer,
final String model,
final String platform){
this.manufacturer = manufacturer;
this.model = model;
this.platform = platform;
}
public String getManufacturer(){
return manufacturer;
}
public String getModel(){
return model;
}
public String getPlatform(){
return platform;
}
#Override
public int hashCode(){
return Objects.hashCode(manufacturer, model, platform);
}
#Override
public boolean equals(final Object obj){
if(obj instanceof Product){
final Product other = (Product) obj;
return Objects.equal(manufacturer, other.manufacturer)
&& Objects.equal(model, other.model)
&& Objects.equal(platform, other.platform);
}
return false;
}
#Override
public int compareTo(final Product o){
return ComparisonChain
.start()
.compare(manufacturer, o.manufacturer)
.compare(model, o.model)
.compare(platform, o.platform)
.result();
}
}
Now I'd just use a TreeSet<Product> and apply views on it. Here's a sample method that returns a live view that is filtered by model:
public static Collection<Product> filterByModel(
final Collection<Product> products,
final String model){
return Collections2.filter(products, new Predicate<Product>(){
#Override
public boolean apply(final Product product){
return product.getModel().equals(model);
}
});
}
Use it like this:
Collection<Product> products = new TreeSet<Product>();
// add some products
Collection<Product> filtered = filterByModel(products, "A1");
Update: We can take it even further, using only one collection, backed by chained predicates that are in turn tied to a model backed by your view. Brain hurts? Check this out:
// this is the collection you sent to your view
final Collection<Product> visibleProducts =
Collections2.filter(products, Predicates.and(Arrays.asList(
new ManufacturerPredicate(yourViewModel),
new ModelPredicate(yourViewModel),
new PlatformModel(yourViewModel)))
);
yourViewModel is an object that is backed by the values returned from your form controller. Each predicate uses a field of this model object to decide whether it applies or not.
e.g. The ModelPredicate checks all products in the collection to see whether their model is among the selected ones. Since this uses and logic, you can make it a hierarchic structure (if the manufacturer predicate returns false, the model and platform predicates are never called).
I use nested maps for something like that. Use TreeMap to get sorted results:
TreeMap<String, TreeMap<String, Model> manufacturerMap;
TreeMap<String, Model> models = manufacturerMap.get( name );
if( models == null ) {
models = new TreeMap<String, Model>();
manufacturerMap.put( name. models );
}
... etc ...

Categories

Resources