currently I am drawing sequence diagram from java code, I know there are several shortcut extension software exist, still, I want to draw it by my hand and to figure out what is going on.
I am working with these piece of code from java:
import java.util.List;
public static void main(String[] args) {
Student student = new Student(2);
student.addClass(new Class("SE 450"));
student.addClass(new Class("SE 550"));
System.out.println(student.getFormattedSchedule());
}
class Student {
//instance field;
private final List<Class> classes;
private final int maxNumberOfClasses;
//constructor
Student(int maxNumberOfClasses){
classes = new ArrayList();
this.maxNumberOfClasses = maxNumberOfClasses;
}
//Mutator Method
void addClass(Class newClass){
if(classes.size() < maxNumberOfClasses)
classes.add(newClass);
}
List<Class> getClasses(){
return classes;
}
String getFormattedSchedule(){
if(classes.size() == 0)
return "No classes added.";
String schedule = "";
for (Class studentClass : classes) {
schedule += studentClass.getName() + "\r\n";
}
return schedule;
and what I draw from this code something like that:
In this case, I do not know how to continue to draw the diagram because i do not know how draw the diagram for this piece of code:
classes.add(newClass);
Does anyone have idea about that? Any suggestions are appreciated!
Well, you could treat classes as an own lifeline and send the add message to it. But that just looks like overkill. Either
you model it sort of a self-message (accompanied by a note) or
you just use a note at the location
or (what I suggest) you don't go into that detail.
An SD is no visual programming aid. It shall give an overview of complex procedures so one get's an idea of what's going on. Reduce to the max.
Related
I am working on a homework assignment that takes input from a .csv file and will prompt the user for different questions pertaining to the information contained within (crime statistics).
My code is as follows and it's still really early so I just have some placeholder variables in there as I have been wracking my head trying to figure out the best approach to this problem.
import java.io.*;
public class USCrimeArray {
String crimeArray[][] = new String[21][20];
public void createCrimeArray() throws Exception{
String crimeArrayInputString;
int crimeArrayRowValue = -1;
try (BufferedReader crimeArrayInput = new BufferedReader(new FileReader("C:/Users/Joey/Documents/Crime.csv"))) {
while ((crimeArrayInputString = crimeArrayInput.readLine()) != null) {
crimeArrayRowValue++;
crimeArray[crimeArrayRowValue] = crimeArrayInputString.split(",");
}
} catch (IOException io) {
io.getMessage();
}
}
public USCrimeArray(){
String[][] thisArray = crimeArray.clone();
}
public String[][] getCrimeArray(){
return crimeArray.clone();
}
}
This is the code for my first class and if I do a deepToString inside of createCrimeArray I get the information back that I want. The constructor for USCrimeArray hasn't really been thought out yet my main question is how to write the information to the crimeArray[][] so that I can carry it back over to other classes.
Once again this test main hasn't been thought out too far because I am still struggling with why my method is not writing over the crimeArray[][] with the while loop and it is as follows:
import java.util.Arrays;
public class USCrimeClass {
public static void main(String[] args) {
USCrimeArray crimeArray = new USCrimeArray();
String[][] test = crimeArray.getCrimeArray();
System.out.println(Arrays.deepToString(test));
}
}
I know there's a lot I'm doing wrong here, but this is the end result so far after having altered everything over and over again and not making any progress. The result of the system out in this is obviously just a 21x20 array of null elements. Any help would be greatly appreciated.
You need to call createCrimeArray() in USCrimeClass
public class USCrimeClass {
public static void main(String[] args) {
USCrimeArray crimeArray = new USCrimeArray();
crimeArray.createCrimeArray();
String[][] test = crimeArray.getCrimeArray();
System.out.println(Arrays.deepToString(test));
}
}
Also,
in the constructor of USCrimeArray you are clonning the array into a local variable thisArray but never use it. this is redundant and can be safely removed.
in getCrimeArray() you are returning a clone of the array. this is not needed (unless you want to keep USCrimeArray immutable). you can just return the array itself
Instance variables
instance variables are non static class level variables (much like crimeArray).
One can consider instance variables as serving two purposes:
"details" of the problem domain of the class. For example Person class will have instance variables such as firstName and lastName that are details of one person.
"configuration" variables holding information related to the technological environment and not pertaining to the problem domain of the class. For example, one sometimes might find a class with a boolean deleted instance variable that signifies a "soft deleted" instance that is not to be presented to the user or included in calculations. the purpose behind this is to support undo of deletion.
so crimeArray is of category details of USCrimeArray. common best practice is to initialise instance variables in the class constructor, so by the time you finish creating a new instance, you have one that has full and valid details. So I would move all of the code of createCrimeArray() into the constructor.
If you need to modify an instance variable after it was initialised, then a "setter" method can be used. these have a standardized signature: public void setCrimeArray(crimeArray[][]). having a standardized signature allows your class to be used by frameworks and libraries that add functionality. For example, storing the data in a relational database, sending/recieving the data over the internet, etc.
Now, I see that the external input that is used to populate the array comes from a file. The way it is coded now, USCrimeArray can only read one specific file from predetermined file syatem location. a more flexible way would be for the class to receive the specification for external input as an argument:
public USCrimeArray(String filename) {
...
try (BufferedReader crimeArrayInput = new BufferedReader(new FileReader(filename))) {
...
}
now the same class can be used to process an array from different files.
now you can even make the file name an argument of the java program:
public class USCrimeClass {
public static void main(String[] args) {
USCrimeArray crimeArray = new USCrimeArray(arg[0]);
System.out.println(Arrays.deepToString(test));
}
}
now the same java program can process different files without need for recompile.
I would like to ask if there is a way to restrict a certain class to make more than a certain amount of instances. And if it is possible to make the compiler ("Eclipse") underline that line, when you try to make another instance (like it is an error in the code), or something along those lines?
Just to clarify for those who would say this is a bad idea, I am making a chess game, so I need it to not be able to make more than certain amount of playing pieces.
Eclipse can't do that at compile time, because it can't tell how many times a piece of code will be executed, and thus how many instances are created.
But you can design your class to only create a given number of instances, and make it impossibale to create more. For example:
public class Limited {
public static final List<Limited> ALL_INSTANCES =
Collections.unmodifiableList(createInstances());
private int id;
private static List<Limited> createInstances() {
List<Limited> result = new ArrayList<>();
for (int i = 0; i < 10; i++) {
result.add(new Limited(i));
}
}
private Limited(int id) {
this.id = id;
}
}
Since the constructor is private, the only 10 instances available are the ones in ALL_INSTANCES.
That said, that is not necessarily a good idea. Let's say you're creating a chess game. So by your logic, you shouldn't be able to create more than 2 King instances. What if your app handles 10 games at a time? Do you really want at most 2 Kings, or do you just want each ChessGame instance to have a black and a white King? Maybe all you need is something like
public class ChessGame {
private King blackKing = new King(BLACK);
private King whiteKing = new King(WHITE);
...
}
You can simply create the required number of objects - say by instantiating your class within a loop and then set a flag which is checked by the constructor so as to throw exception when an attempt is made to create one more. You can make the constructor private and have a static method to generate your instances.
I'm learning about Sets and Maps in the Introduction to Java Programming book by Daniel Liang. My professor has assigned a problem in the back of the chapter that asks me to create a program that:
Queries the user for input on name
Queries the user for gender
Using these two criteria, and this/these website(s): http://cs.armstrong.edu/liang/data/babynamesranking2001.txt
... http://cs.armstrong.edu/liang/data/babynamesranking2010.txt
I have to be able to get the ranking.
I'm supposed to get this information into an array of 10 maps.
Each map corresponds with a .txt file/year. This is where I'm having problems with. How do I do this?
The (Int) rank of the student is the value of the map, and the key is the name (String) of the baby.
The way I was thinking was to create an array of maps or maybe a list of them. So like:
List<Map<Int, String>> or <Map<Int, String>[] myArray;
Yet even after that the issue of how I get all of this information from the .txt file to my maps is a hard one for me.
This is what I've come up so far. I can't say I'm happy with it. It doesn't even work when I try to start reading information is because I haven't specified the size of my array.
public class BabyNamesAndPopularity
{
public static void main (String[] args) throws IOException
{
Map<Integer, String>[] arrayOfMaps;
String myURL = "cs.armstrong.edu/liang/data/babynamesranking2001.txt";
java.net.URL url = new java.net.URL(myURL);
Scanner urlInput = new Scanner (url.openStream());
while(urlInput.hasNext())
{
...
}
}
}
Would it be viable to make a set OF MAPS? I was kind of thinking it would be better to make a set OF maps because of the fact that sets expand as needed (according to the load factor). I just need some general guidance. Unfortunately the CS program at my university (Francis Marion University in Florence, SC) is VERY small and we don't have any tutors for this stuff.
This answer rather vague, because of broad nature of question, and it may be more suitable for
programmers SE site. Still, you may find these two points worth something.
Instead of thinking in terms of 'raw' compound collections, such as lists of maps of sets or such, try to invent set of domain types, which would reflect your problem domain, and, as the next step, implement these types using suitable Java collections or arrays.
Unit-testing and incremental refinement. Instead of immediately starting with access to remote data (via java.net.URL), start with static source of data. Idea here is to have 'reliable' and easily accessible input data hand, which would allow you to write unit tests easily and w/o access to network or even to file system, using set of domain types from 1st point, above. As you write unit tests you can invent necessary domain types/methods names in unit tests at first, then implement these types/methods, then make unit tests pass.
For example, you may start by writing following unit test (I assume you know how to organize your Java project in your IDE, so unit test(s) can be run properly):
public class SingleFileProcessingTest {
private static String[] fileRawData;
#BeforeClass
public static void fillRawData() {
fileRawData = new String[2];
// values are from my head, resembling format from links you've posted
fileRawData[0] = "Jacob\t20000\tEmily\t19999";
fileRawData[1] = "Michael\t18000\tMadison\t17000";
}
#Test
public void test() {
Rankings rankings = new Rankings();
rankings.process(fileRawData);
assertEquals("Jacob", rankings.getTop().getName());
assertEquals("Madison", rankings.getScorerOfPosition(4).getName());
assertEquals(18000, rankings.getScoreOf("Michael"));
assertEquals(4, rankings.getSize());
}
}
Of course, this won't even compile -- you need to type in code of Rankings class, code of class returned by getTop() or getScorerOfPosition(int) and so on. After you made this compile, you'll need to make test pass. But you get main idea here -- domain types and incremental refinement. And easily verifiable code w/o dependencies on file system or network. Just plain old java objects (POJOs). Code for working with external data sources can be added later on, after you get your POJOs right and make tests, which cover most parts of your use cases, pass.
UPDATE Actually, I've mixed up levels of abstraction in code above: proper Rankings class should not process raw data, this is better to be done in separate class, say, RankingsDataParser. With that, unit test, renamed to RankingsProcessingTest, will be:
public class RankingsProcessingTest {
#Test
public void test() {
Rankings rankings = new Rankings();
rankings.addScorer(new Scorer("Jacob", 20000));
rankings.addScorer(new Scorer("Emily", 19999));
rankings.addScorer(new Scorer("Michael", 18000));
rankings.addScorer(new Scorer("Madison", 17000));
assertEquals("Jacob", rankings.getTop().getName());
// assertEquals("Madison", rankings.getScorerOfPosition(4).getName());
// implementation of getScorerOfPosition(int) left as exercise :)
assertEquals(18000, rankings.getScoreOf("Michael"));
assertEquals(4, rankings.getSize());
}
}
With following initial implementation of Rankings and Scorer, this is actually compiles and passes:
class Scorer {
private final String name;
private final int rank;
Scorer(String name, int rank) {
this.name = name;
this.rank = rank;
}
public String getName() {
return name;
}
public int getRank() {
return rank;
}
}
class Rankings {
private final HashMap<String, Scorer> scorerByName = new HashMap<>();
private Scorer topScorer;
public Scorer getTop() {
return topScorer;
}
public void addScorer(Scorer scorer) {
if (scorerByName.get(scorer.getName()) != null)
throw new IllegalArgumentException("This version does not support duplicate names of scorers!");
if (topScorer == null || scorer.getRank() > topScorer.getRank()) {
topScorer = scorer;
}
scorerByName.put(scorer.getName(), scorer);
}
public int getSize() {
return scorerByName.size();
}
public int getScoreOf(String scorerName) {
return scorerByName.get(scorerName).getRank();
}
}
And unit test for parsing of raw data will start with following (how to download raw data should be responsibility of yet another class, to be developed and tested separately):
public class SingleFileProcessingTest {
private static String[] fileRawData;
#BeforeClass
public static void fillRawData() {
fileRawData = new String[2];
// values are from my head
fileRawData[0] = "Jacob\t20000\tEmily\t19999";
fileRawData[1] = "Michael\t18000\tMadison\t17000";
}
#Test
public void test() {
// uncomment, make compile, make pass
/*
RankingsDataParser parser = new RankingsDataParser();
parser.parse(fileRawData);
Rankings rankings = parser.getParsedRankings();
assertNotNull(rankings);
*/
}
}
Sorry, this might be duplicated, I'm not sure if my previous attempt to post this went through.
Started to learn Java several weeks ago, working on one of my first assignments. :)
My question is somewhat basic, but I couldn't find its exact equivalent after looking through previously resolved topics. This isn't a real life problem, so I guess it's expected from me to tackle it in a very specific way.
So the task consisted of several steps - I had to create a superclass with a number of custom objects, add new subclasses, implement new methods to count the value of certain variables, write test classes and sort my output.
It's all been done apart from this last step. Not sure if I'm allowed to just post my problems like that on the web, but here is where I am right now:
I have something like:
public class Pants
{
public enum SizeType {SMALL, MEDIUM, LARGE, EXTRA_LARGE}
private SizeType size;
private String brand;
private String countryOfOrigin;
private String color;
private double price;
//Other variables and methods
}
public class Jeans extends Pants
{
//new variables and methods
}
public class Shorts extends Pants
{
//some more new variables and methods
}
And other similar subclasses.
import java.util.ArrayList;
public class Selection
{
public static void main(String[] args){
Jeans ex1 = new Jeans("John Lewis");
ex1.countryOfOrigin("US");
ex1.color("Navy");
ex1.setSize(Pants.SizeType.LARGE);
ex1.setprice(40);
ex1.machineWashable(true);
System.out.println(ex1);
Shorts ex2 = new Shorts("Ted Baker");
ex2.countryOfOrigin("United Kingdom");
ex2.color("White");
ex2.setSize(Pants.SizeType.MEDIUM);
ex2.setprice(30);
ex2.machineWashable(true);
System.out.println(ex2);
//..etc
ArrayList<Pants> selection = new ArrayList<Pants>();
selection.add(ex1);
selection.add(ex2);
selection.add(ex3);
selection.add(ex4);
selection.add(ex5);
System.out.println( "Size - LARGE: " );
System.out.println();
Pants.SizeType size;
size = Pants.SizeType.LARGE;
ListPants(selection,size);
I need to write a ListPants method to list objects depending on SizeType - starting with large in this case. I don't think I can implement any additional interfaces (which is what was mostly recommended in other threads).
Please see my attempt below (didn't work). Am I thinking in the right direction here, or?
public static void ListPants(ArrayList<Pants> selection, Pants.SizeType size)
{
for (Pants.SizeType sizeType : Pants.SizeType.values()) {
for (Pants pants : selection) {
if (pants.getSize().equals(sizeType)) {
System.out.println(selection.toString());
I think it's just a minor problem you're facing. You already defined the signature of the method which should print out all pants of a specific size:
ListPants(ArrayList<Pants> selection, Pants.SizeType size)
That is correct. Now, your code is looping over all pants and over all possible sizes:
public static void ListPants(ArrayList<Pants> selection, Pants.SizeType size)
{
for (Pants.SizeType sizeType : Pants.SizeType.values()) {
for (Pants pants : selection) {
if (pants.getSize().equals(sizeType)) {
System.out.println(selection.toString());
Since this looks like a homework assignment, i'll phrase my answer as a question:
Where are you using the size parameter in the method body of ListPants?
I am assuming your class cannot implement new interfaces, and not using interfaces at all.
You can use Collections.sort(List,Comparator) with a Comparator, which is built for your class.
Something like
Collections.sort(selection,new Comparator<Pants>() {
#Override
public int compare(Pants p1, Pants p2) {
//implement your compare method in here
...
}
});
If you are eager to create your own sorting algorithm, have a look of this list of sorting algorithms. Simplest to implement (though pretty slow) IMO is selection-sort
Been a while since I used Java and was wondering if this was a decent or even correct way of setting this up.
FYI, userResults refers to a JDBI variable that isn't present in the code below.
Feel free to suggest a better method, thanks.
public class Stat
{
private int current;
private int max;
public int getCurrent() {return current;}
public void setCurrent(int current) {this.current = current;}
public int getMax() {return max;}
public void setMax(int max) {this.max = max;}
}
public class Character
{
Stat hp = new Stat();
Stat mp = new Stat();
}
Character thisCharacter = new Character();
// Set the value of current & max HP according to db data.
thisCharacter.hp.setCurrent((Integer) userResults.get("hpColumn1"));
thisCharacter.hp.setMax((Integer) userResults.get("hpColumn2"));
// Print test values
System.out.println (thisCharacter.hp.Current);
System.out.println (thisCharacter.hp.Max);
Correct? Well, does it work? Then it probably is correct.
Wether or not it is a decent way to do it then the answer is "maybe". It is hard to tell from what context this code is in. But there are some things you could keep in mind though:
In which class (or object rather) are the Stat set in? Do you feel is it the responsibility of the class to do this and know what database values to get them from? If not, consider making some kind of a class that does this.
Making chained calls such as thisCharacter.hp.setCurrent(...) is a violation of principle of least knowledge. Sometimes you can't help it, but usually it leads to kludgy code. Consider having something that handles all the logic surrounding the stats. In your code you may need a HealthStatsHandler that have methods such as loadStats(), saveStats(), and mutator actions such as takeDamage(int dmg) and revive(int health).
If you have trouble figuring things out if it has the correct object design, then study up on the SOLID principles. They provide nice guidelines that any developer should follow if they want to have code that is extensible and "clean".
This is not really a tree. It is not possible two have more than one layer of children.
Usually you define an interface let's call it Node where both Stat and Character implements it and the two children of Character would have the type Node.
I would consider creating the Stat objects seperately and passing them into Character, and making the character attributes private as follows:
public class Character
{
private Stat hp;
private Stat mp;
public Stat getHp() {return hp;}
public void setHp(Stat h) {this.hp = h;}
public Stat getMp() {return mp;}
public void setMp(Stat m) {this.mp = m;}
}
// Set the value of current & max HP according to db data.
Stat hp = new Stat();
hp.setCurrent((Integer) userResults.get("hpColumn1"));
hp.setMax((Integer) userResults.get("hpColumn2"));
Character thisCharacter = new Character();
thisCharacter.setHp(hp);
// do the same for mp
One additional simple step would be to create a Character constructor that would take an hp and an mp