java how to add variables to an object from a string - java

I have two objects that are being stored in arrays:
Game(String creator, String title, int releaseYear, int NumberSold)
Creator(String name, String gamesWorkedOn)
Game(creator) has multiple creators, so is stored as a string like this: "creator1, creator2, creator3" using commas to separate their values.
Not all games have multiple creators and there are not many different creators in total.
What I am trying to do is loop through an array of Game(games) and extract a creator variable from it and assign it to the Creator(name) and then match any games that creator is mentioned in and assign those title variables to Creator(gamesWorkedOn).
So far I have this:
public static void PopulateCreators(ArrayList<Game> games) {
//populating an array of Creators with games they have worked on
boolean match = false;
String thisCreator;
String gamesWorkedOn;
ArrayList<Creator> creatorArray = new ArrayList<Creator>();
for (int i = 0; i < games.size(); i++) {
thisCreator = games.get(i).getGameCreator();
thisCreator = thisCreator.replaceAll(", ", "\n");
Which gives me this output using a sysout:
Shigeru Miyamoto
Satoshi Tajiri
Yoshiaki Koizumi
Koichi Hayashida
Shigeru Miyamoto
My desired output would be to have something like this:
name = "Shigeru Miyamoto"
gamesWorkedOn = "game1, game2, game3"
I am looking at using a for loop but am unsure on how to implement it here.
Edit:
I forgot to mention a couple of details that I didn't think were important but I will be a bit clearer now. This is a Swing based project I am working on that takes user inputs and stores these arrays which are then saved into a JSON file that is read upon loading of the application and when a user clicks a 'save' button.

What you seem to want to do is map the creators to all the games that they have created or helped create. I'm going to start by creating a simplified version of the problem.
You have a list of:
class Game {
Set<Creator> creators;
}
which you want to convert to:
Map<Creator, Set<Game>> createdGames; // Map of creator name to games created
The first thing to do here is to find all of the unique creators to start adding to the map. This can be done with the stream API.
createdGames = gameList.stream().flatMap(game -> game.creators.stream()).distinct().collect(Collectors.toMap(Function.identity(), v -> new HashSet<>()));
Now you can just loop through all the games again and add the game to a creator's set if they took part in the creation of that game.
for(Game game : gameList) {
for(Creator creator : createdGames.keySet()) {
if(game.creators.contains(creator)) {
createdGames.get(creator).add(game);
}
}
}

Related

Bukkit: How to permentately store player and class information?

Currently, I'm writing a RPG plugin. I've created a PlayerInfo class that stores the player's UUID, character class like knight and archer, and skills that modify a player's attributes, e.g. vitality would increase a players health, strength would increase a player's physical damage, and so on.
Here's the class so far:
public class PlayerInfo {
public String suuid;
public String charClass;
public int vitality;
public int strength;
public int defense;
public int dexterity;
public int intelligence;
public int faith;
public PlayerInfo() {
}
public PlayerInfo(String UUID, String characterClass, int VIT, int STR, int DEF, int DEX, int INT, int FAI) {
suuid = UUID;
charClass = characterClass;
vitality = VIT;
strength = STR;
defense = DEF;
dexterity = DEX;
intelligence = INT;
faith = FAI;
}
I'd like to say as well that I'm primarily a Python and Javascript programmer. I picked up Java about 2 days ago, so I apologize if my code is unhygienic. I'm still trying to understand the languages and its practices. If you would like, I'd appreciate any advice on that as well. Though, feel free to just answer my base question, as I will be posting to Code Review, too, at some point in the future.
Moving forward...
While working on the basic framework of this plugin, I've realized that the information within the PlayerInfo class is most likely not saved when the server is stopped. I thought that possibly I could write the information, using FileOutputStream and ObjectOutputStream, to a file, and store that in a config folder, and later retrieve it with the Input versions of those modules. However, I ran into an issue when trying to dynamically pick up the path of the jar file, as my server told me that my Access was denied when trying to create the folder and file.
My last issue comes when trying to use the loaded information. My plugin's commands start with /static. If I had a command named /static stats that displayed the users stats, would it be as simple as comparing the user's UUID to the one stored in the save file? For example:
Player player = (Player) sender;
String suuid = player.getUniqueId().toString();
if (character.suuid == suuid) {
// Load stats here...
}
Or is there a different way to go about doing it?
To condense my post down a bit:
How can I store Player and class information effectively, and how can I later retrieve that data to use for information and see if the current player matches a saved object? Is this what stuff like SQL is used for?
Load each player when they connect to the server into a memory (make a new PlayerInfo Object for each of them, using for example a HashMap or a List).
On player disconnect you have to save all the information into a file/database (sql included) which is being restored and loaded again on next connect of the given player.
The information is being lost when server stops, therefore you need to store it somewhere and retrieve it when you need it.
You can create a simple function to retrieve a PlayerInfo based on a HashMap
HashMap<String, PlayerInfo> allplayers = new HashMap<String, PlayerInfo>();
public PlayerInfo getPlayer(Player player){
if(allplayers.containsKey(player.getName())){
return allplayers.get(player.getName());
}else{
return null;
}
}
And to put players into a HashMap
public void addPlayer(Player player){
if(!allplayers.containsKey(player.getName())){
//Load playerInfo
PlayerInfo p = new PlayerInfo(....);
//put into hashmap
allplayers.put(player.getName(), p);
}
}
//saving PlayerInfo can be called on PlayerDisonnect/Server shutdown
public void savePlayer(Player player){
if(allplayers.containsKey(player.getName())){
PlayerInfo p = allplayers.get(player.getName());
//Save information
.....
//remove player from HashMap
allplayers.remove(player.getName());
}
} `
Okay , u can use serialization on your class , and i guess its the way cause u have just the primitives , and then u can byte write ur created serialization file to a sql database , and when u need it , u can again read it back and type cast it to ur class object . Then u can invoke an iterator to loop through the propertises and find matches for ur player with .equals method .

Creating a schedule of Game Objects in Java

I'm in the process of developing a stat tracker for Baseball season. I'd like to be able to load an entire schedule ino the program, making each game a relatively simple object.
Creating the game object isn't an issue. What I'm wondering is, what's the best way to implement the schedule? I have, in the team class, an ArrayList schedule.
I need a way to load the schedule info from a text file, loop through it and create a game object for each line. If that's not the best way to create 162 objects efficiently, please let me know.
Cheers
EDIT:
The game class is really very simple:
public class Game implements Serializable{
Date gameDate;
Team team;
public int runsScored, runsAllowed;
public ArrayList<BallPlayer> lineup = new ArrayList<BallPlayer>();
public ArrayList<Pitcher> pitchers = new ArrayList<Pitcher>();
public Pitcher starter;
String opponent;
boolean homeAway;
boolean result;
public Game(Team gTeam, Pitcher gStarter, String gOpponent, String homeOrAway, Date gDate){
this.team = gTeam;
this.starter = gStarter;
this.opponent = gOpponent;
if(homeOrAway.equalsIgnoreCase("home")){this.homeAway = true;}
this.runsScored = 0;
this.runsAllowed = 0;
gameDate = gDate;
}
public String getOpponent(){return opponent;}
public void setOpponent(String o){this.opponent = o;}
public boolean getHomeAway(){return homeAway;}
public void setHomeAway(String ho){if(ho.equalsIgnoreCase("home")){this.homeAway = true;}else{this.homeAway = false;}}
}
This is a pretty general question but I thought I would give you some thoughts on how I would initially approach this.
For your models, you could start with something like this:
GameVO (id, home team id (TeamVO), away team id (TeamVO), location id, schedule_id)
TeamVO (id, mascot, name, hometown, etc.)
LocationVO (id, city, state, stadium name, etc.)
PlayerVO(id, position, fname, lname, number, team_id, array_of_stat_ids)
StatVO(id, game_id, player_id, base_hits, home_runs, rbi, strike_out, etc)
ScheduleVO(id, location_id, home_team_id, away_team_id, play_time)
For the text file, I would recommend becoming comfortable with Regular Expressions. Regular expressions allow you to read in strings of data and extract data based on the patterns that you specific. Your text file will either be a fixed-length text-file, comma separated values (CSV), or some other format (first make sure you understand how your data is structured). Once you have identified the patterns that you want to extract, create your regex to match on every line and extract the appropriate values. Here is a good place to practice with your Regex
Finally, when seriallizing your objects take a look at seriallizers like XStream for .NET. I liked the Java version of this library as it allows you to quickly turn java objects into XML/json and back again.

Making an add method for an ArrayList

So I am supposed to make an add method for an array list which adds a new movie object to the list if it doesnt exist, or if it finds a movie object with a similar title within the list, it just increases the quantity property of that object. Here is what I've got so far.
public void add(String title, double rating, int releaseYear){
if(this.myMovies.size() < 1)
{
Movie mymovie = new Movie(title, rating, releaseYear);
this.myMovies.add(mymovie);
}
else
{
for(int i = 0; i < this.myMovies.size(); i++)
{
Movie temp = this.myMovies.get(i);
if(temp.Title.equals(title)){
this.myMovies.get(i).quantity++;
break;
}
else
{
Movie mymovie = new Movie(title, rating, releaseYear);
this.myMovies.add(mymovie);
break;
}
}
}
}
My problem is that this ends up not taking account of similar names and doesn't increase the quantity but just adds another object to the list. I have a strong feeling that the problem lies within my For loop but I just can't identify it. Can anyone see anything that I may be doing wrong? Thank you!
You're testing only for equality, not similarity here:
if(temp.Title.equals(title)){
Instead, you should write a helper method to test for similarity based on whatever criteria are appropriate. For example:
if (isSimilar(temp.Title, title)){
and the isSimilar method might look something like this (assuming you don't need any input validation):
private void isSimilar(String title1, String title2) {
return title1.equalsIgnoreCase(title2)
|| title1.toLowerCase().contains(title2.toLowerCase())
|| title2.toLowerCase().contains(title1.toLowerCase());
}
or, perhaps more appropriately, like this (if you implement it in the Movie class):
private void isSimilar(otherMovie) {
return title.equalsIgnoreCase(otherMovie.title)
|| title.toLowerCase().contains(otherMovie.title.toLowerCase())
|| otherMovie.title.toLowerCase().contains(title.toLowerCase());
}
...in which case your if statement would also change slightly.
Keep in mind that I don't know what you consider 'similar'; only that the movies are considered similar if the names are similar.
A couple more comments:
Fields and method names generally start with a lowercase letter (so the field Movie.Title should instead be Movie.title).
It's usually preferable to loop over a Collection using an Iterator instead of using the raw index--partly because the Iterator should always know how to loop over the Collection efficiently.
Learn to use your IDE's debugger (it's probably very easy). Then you can step through each line of code to see exactly where your program is doing something unexpected.
I would do something like this:
public void add(String title, double rating, int releaseYear){
for(Movie m: myMovies.size())
{
if(m.Title.equals(title)){
m.quantity++;
return;
}
}
// movie with same title not found in the list -> insert
this.myMovies.add(new Movie(title, rating, releaseYear));
}
By the way: variable names should start with a lowercase character (Title -> title).
I'm addressing your "similarity" requirement. If you really want to do this properly it could be a lot of work. Essentially you have two strings and want to get a measure of the similarity. I am doing the same thing for figure captions and I plan to tackle it by:
splitting the title into words
lowercasing them
using them as features for classifier4J (http://classifier4j.sourceforge.net/)
That will go a long way based on simple word counts. But then you have the problem of stemming
(words that differ by endings - "Alien" and "Aliens"). If you go down this road you'll need to read up about Classification and Natural Language Processing

Java Object Instance creation problems

So I've been struggling all day today trying to create an instance of a class called 'Sport'.
I've got my code set up so I run the User Interface, which then runs a constructor, which then runs another constructor which loads the Sport values from a text file.
The problem is, the way I'm apparently creating the objects is wrong. Could really use some help.
public static void seperateValues(String sportDetail)
{
String[] sportDetails = sportDetail.split(",");
System.out.println("Adding new sport to the Sport collection");
System.out.println(sportDetail);
/*
for(int i=0; i<sportDetails.length; i++) //just used for testing whether it was splitting correctly
{
System.out.println(sportDetails[i]);
} */
// name,usagefee,insurance,affiliationfees, then court numbers
//Tennis,44,10,93,10,11,12,13,14,15,16
int vlength;
vlength = sportDetail.length();
String[] sportDetailz;
sportDetailz = new String[vlength];
sportDetailz[0] = sportDetails[0]; //name
sportDetailz[1] = sportDetails[1]; //usage fees
sportDetailz[2] = sportDetails[2]; //insurance
sportDetailz[3] = sportDetails[3]; //afflcationfees
String vSportObjectName;
vSportObjectName = sportDetails[0];
String sportinstance;
sportinstance = sportDetails[0]; //this is the name of the sport which I'm hoping each loop around
//it will give a new name to
Sport sportinstance = new Sport(sportDetails);
//System.out.println(Sport.this.name);
}
Error message: variable sportinstance is already defined in method seperateValues(java.lang.String)
http://puu.sh/2zil9
I'm guessing your issue is that you first declare sportinstance as a String. You then try to define it again as a Sport.
Just remove the following lines and try again (as it doesn't look like they actually are used anywhere else):
String sportinstance;
sportinstance = sportDetails[0];
The other option would be to simply rename either one of your instances of sportinstance.
You are trying to define sportinstance as two different datatypes and Java will not allow this. Either change the name of the Sport definition of sportinstance to another variable name or remove the definition.

Java: For loop and If algorithm

I've this question from an assignment to create a Store which rent out books, using a Store.java and Book.java. I've finished this assignment, but I'm curious for better algorithm to a specific part.
--
Book.java
public class Book {
private String name;
Book(String name)
this.name = name;
public String getName()
return name;
}
Store.java
Inside main();
Book bookObj[] = new Book[3]; //Create 3 Array of Object.
bookObj[0] = new Book("Game Over");
bookObj[1] = new Book("Shrek");
bookObj[2] = new Book("Ghost");
Scanner console = new Scanner(System.in)
input = console.nextLine();
Assuming, input = Devil.
Now, I need to do a simple search to check whether the specific book exist.
Example:
for(int i = 0; i < bookObj.length; i++) {
if(bookObj[i].getName().equals(input))
System.out.println("Book Found!");
}
Apparently, this is a for loop that cycles through the array of object and checks whether such Book exist. Now, the problem arise when I want to give an output that the Book was not found.
Example:
for(int i = 0; i < bookObj.length; i++) {
if(bookObj[i].getName().equals(input))
System.out.println("Book Found!");
else
System.out.println("Book not Found!");
}
The problem with the above code is that Book not Found would be printed thrice. My goal is to avoid such problem. I do have solutions to this, but I'm still in search for a better one to use that utilizes getName(), which in my opinion still has room to improve.
Usually, in structural programming, I would do the following,
for(int i = 0; i < bookObj.length; i++) {
if(bookObj[i].getName().equals(input))
System.out.println("Book Found!");
else if(i == bookObj.length - 1)
System.out.println("Book not Found!");
}
This is useful to tell whether it's the end of the loop, and the search has ended, but there was no successful result from the search.
How should I think of it in Object Oriented way?
All in all, my question is,
Is there a better way to write the above code rather than checking that it's the end of the line?
Is there a better way to utilize getName() method or to use other methods?
You should loop through the array and use an index / boolean flag to store whether or not the book is found. Then print the message in the end, based on the index / flag value.
int foundAtIndex = -1;
for(int i = 0; i < bookObj.length; i++) {
if(bookObj[i].getName().equals(input)) {
foundAtIndex = i; // store the actual index for later use
break; // no need to search further
}
}
if(foundAtIndex >= 0)
System.out.println("Book Found!");
else
System.out.println("Book not Found!");
Alternatively (unless your assignment specifically requires using an array) you should prefer a Set, which can do the search for you with a single call to contains().
How should I think of it in Object Oriented way?
When looking at a single method, there is not much difference between procedural and OO style. The differences start to appear at a higher level, when trying to organize a bunch of conceptually related data and methods that operate on these.
The OO paradigm is to tie the methods to the data they operate on, and encapsulate both into coherent objects and classes. These classes are preferably representations of important domain concepts. So for your book store, you may want to put all book related code into your Book class. However, the above search method (and the collection of books it operates on) is not related to any particular book instance, so you have different choices:
put both the collection of books and the search method into Store (probably as regular members), or
put them into Book as static members.
The first choice is more natural, so I normally would prefer that. However, under specific circumstances the second option might be preferable. In (OO) design, there are hardly ever clean "yes/no" answers - rather tradeoffs between different options, each having their own strengths and weaknesses.
You could introduce state and remember whether you have found the book or not.
If you're not using Java 1.4 or earlier, you could also use the foreach loop syntax:
boolean bookFound = false;
for(Book currentBook : bookObj) {
if(currentBook.getName().equals(input))
//TODO: see above
}
Also, I would suggest looking into the Collections library, and replace your array with a list or set:
Set<Book> books = new HashSet<Book>();
books.put(new Book("Game Over"));
books.put(new Book("Shrek"));
books.put(new Book("Ghost"));
And, while were at it, you could also think about when two books are equal and override equals() and hashCode() accordingly. If equal() would be changed to check the title, you could simply use books.contains(new Book(input)); and have the libraries do the work for you.
To solve the problem in a better way you must understand that the power of Java comes not from the language itself but from the Java Framework.
You should learn the usage of the Java Collection classes (never work with arrays anymore). Then you will be able to solve the search with just one line of code:
ArrayList<Book> listOfBooks;
// init your list here
listOfBooks.contains(new Book(input));
To make this work, you must also learn how to correctly implement the equals() method of your Book class.
Happy learning!
Here is a working solution :
import java.util.Scanner;
public class Store {
private static class Book {
private String name;
Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String[] args) {
String input;
Book[] bookObj = new Book[3];
bookObj[0] = new Book("Game Over");
bookObj[1] = new Book("Shrek");
bookObj[2] = new Book("Ghost");
Scanner console = new Scanner(System.in);
input = console.nextLine();
boolean found = false;
int i = 0;
while(!found && i < bookObj.length) {
if(bookObj[i].getName().equals(input)) {
System.out.println("Book Found at position : " + i);
found = true;
} else {
i++;
}
}
if(!found) {
System.out.println("Book not Found!");
}
// Here i contains the indice of the element found in the array.
}
}
You've gotten some pretty good advice thus far. You asked if there was a more Object Oriented way of thinking about the problem so I thought I'd try and shed some light on it. As Peter already mentioned at this level of the design it's a single method implementation so the approach is going to be fairly similar as say a procedural approach. What's the advantage? In a word reuse. If you needed to find a book by name in lots of places then moving the code to it's own class will help.
So what you have is a single Book instance to encapsulate behavior around a single book, but you want to have behavior about multiple books, or a collection of books. You can keep the data (array of books), and the method that account on them separate as you outlined in your program. However, if we wanted to collect a place for doing behavior on a collection of books we can define a new class. Let's call it Library, and we might do something like the following:
public class Library {
private Book[] books;
private bookCount = 0;
public Library( int numberOfTotalBooks ) {
books = new Book[numberOfTotalBooks];
}
public boolean addBook( Book book ) {
if( bookCount < book.length ) {
books[bookCount++] = book;
return true;
}
return false;
}
public Book findByTitle( String title ) {
for( int i = 0; i < bookCount; i++ ) {
if( books[i].getTitle().equals( title ) ) {
return books[i];
}
}
// didn't find one
return null;
}
}
So a couple of things to note about doing things this way. One is that when we work with a Library we don't know there is an Array back there. We could use an array, a Set, a List, or a database (most common). The point being the code that calls these functions just works with the interface of Library (not a literal Java interface, but the method signature of Library). Also this is a higher level interface. We don't worry about iterating over the books, doing for loops, if statements, etc. We just call a method saying "Hey find this book title in the Library". How that's done we don't care. This is the basic tenant of Object Orientation called encapsulation, and it's deceptively powerful. It's really about how we delegate responsibility in our program, and give the details of a job to individual class or classes. If Library had only public members (i.e. books and bookCount), or getter/setters then the client wouldn't be getting any advantages because the client would still have to do all the heavy lifting. The trick to OO is figuring out what can be delegated out of an object, without creating problems. This takes practice, and experience.
The second thing here is we've separated the presentation from the act of finding a book. The method you wrote assumed the next step which was to print "Hey we found it." However, Library object simply returns the Book to you when it finds it, or null if it didn't. That makes it possible to print to the console, display in a GUI, or serialize it to a JSON stream in a server. The act of finding a book is separate from the visualization. This is another important aspect of programming in general, but some what related to object orientation and encapsulation. This is typically called separation of concerns. The console application has concerns about supporting the UI, and printing the console. While the Library just manages cataloging and managing the book collection. How those details are performed neither cares.
In the end Library is a reusable class. We can use it in a console application, desktop, web, or middleware server. More importantly is we can also reuse the calls to findByTitle or addBooks from multiple locations within a single program. Also by putting the methods with the data we create a barrier to where that function can be used. You can't do it anywhere in your program. You have to have a reference to Library. If you don't have reference to a Library instance then you shouldn't be calling it. This can be troublesome to new developers because they lack the experience to properly organize their programs to not get into trouble with this (then they start doing value objects, creating statics, singletons, etc and things turn into a big ball of mud). It's a double edged sword.
One more thing I'd like to point out is say we wanted to model two Libraries. We have a Library uptown and downtown, and we want to allow people to check out books from either Library. With OO that's really easy to represent:
Library uptown = new Library( 50 );
Library downtown = new Library( 100 );
Now we can check out books from one or the other. And I didn't use statics (i.e. global variables) so reusing that logic is really easy. These are the basics of OO so they are really deep topics. Strange how I can write so much on very simple topics. Anyway I hope this helped you understand your program a little deeper, and see how you can use OO to help you.
chubbsondubs came closest to giving a correct answer to this question
What he missed is that his algorithm is incorrect because it contains two tests, when only one is needed. The correct code requires only 3 statements and is as follows:
public boolean zLibaryContains( String title ) {
books[bookCount] = title;
int xBook = 0;
while( true )
if( books[xBook].getTitle().equals( title ) )
return xBook != bookCount;
else xBook++;
}
Noticeably smaller and faster than all other solutions. Simplify, simplify, simplify.
Object-oriented code is a crutch to support poor designs that would otherwise be too complex to understand. The goal is write code that is so easy to understand and maintain that OO is unnecessary and would make the program worse. When your program can be improved by adding OO, it means you are doing something wrong to begin with.

Categories