Problem
This runs as is, but I’m looking for an alternative way to write it.
import java.util.Scanner;
public class StateBirdAndFlowerProgram {
public static void main(String args[]) {
// Begin Scanner for user input later on
Scanner input = new Scanner( System.in );
//Begin array of information
String[][] states={
{"Alabama", "Flower: Camelia", "Bird: Northern flicker"},
{"Alaska", "Flower: Forget-me-not", "Bird: Willow ptarmigan "},
{"Arizona", "Flower: Saguaro cactus blossom", "Bird: Cactus wren "},
{"Arkansas", "Flower: Apple blossom", "Bird: Northern mockingbird "},
{"Califorina", "Flower: Califorina poppy", "Bird: California quail"},
{"Colorado", "Flower: Rocky Mountian columbine", "Bird: Lark bunting"},
{"Connecticut", "Flower: Mountain laurel ", "Bird: American robin"},
{"Delaware", "Flower: Peach blossom", "Bird: Delaware Blue Hen "},
{"Florida", "Flower: Orange blossom ", "Bird: Northern mockingbird "},
{"Georgia", "Flower: Cherokee rose ", "Bird: Brown thrasher ", },
{"Hawaii", "Flower: Hawaiian hibiscus ", "Bird: Nēnē or Hawaiian goose"},
{"Idaho", "Flower: Syringa, mock orange ", "Bird: Mountain bluebird "},
{"Illinois", "Flower: Violet ", "Bird: Northern cardinal "},
{"Indiana", "Flower: Peony ", "Bird: Northern cardinal "},
{"Iowa ", "Flower: Wild prairie rose ", "Bird: Eastern goldfinch "},
{"Kansas", "Flower: Sunflower", "Bird: Western meadowlark"},
{"Kentucky", "Flower: Goldenrod ", "Bird: Northern cardinal"},
{"Louisiana", "Flower: Magnolia ", "Bird: Brown pelican "},
{"Maine", "Flower: White pine cone and tassel ", "Bird: Black-capped chickadee "},
{"Maryland", "Flower: Black-eyed susan ", "Bird: Baltimore oriole"},
{"Massachusetts", "Flower: Mayflower ", "Bird: Black-capped chickadee "},
{"Michigan", "Flower: Apple blossom", "Bird: American robin "},
{"Minnesota", "Flower:Pink and white lady's slipper ","Bird: Common loon"},
{"Mississippi", "Flower: Magnolia", "Bird: Northern mockingbird "},
{"Missouri", "Flower: Hawthorn", "Bird: Eastern bluebird "},
{"Montana", "Flower: Bitterroot ", "Bird: Western meadowlark "},
{"Nebraska", "Flower: Goldenrod", "Bird: Western meadowlark"},
{"Nevada", "Flower: Sagebrush ", "Bird: Mountain bluebird "},
{"New Hampshire ", "Flower: Purple lilac ", "Bird: Purple finch "},
{"New Jersey", "Flower: Violet ", "Bird: Eastern goldfinch "},
{"New Mexico", "Flower: Yucca flower", "Bird: Roadrunner "},
{"New York", "Flower: Rose", "Bird: Eastern bluebird "},
{"North Carolina", "Flower: Flowering dogwood", "Bird: Northern cardinal "},
{"North Dakota", "Flower: Wild prairie rose ", "Bird: Western meadowlark "},
{"Ohio", "Flower: carlet carnation ", "Bird Northern cardinal: "},
{"Oklahoma", "Flower: Oklahoma rose ", "Bird: Scissor-tailed flycatcher "},
{"Oregon", "Flower: Oregon grape ", "Bird: Western meadowlark "},
{"Pennsylvania", "Flower: Mountain laurel", "Bird: Ruffed grouse"},
{"Rhode Island", "Flower: Violet", "Bird: Rhode Island Red "},
{"South Carolina", "Flower: Yellow jessamine ","Bird: Carolina wren", },
{"South Dakota ", "Flower: Pasque flower ", "Bird: Ring-necked pheasant"},
{"Tennessee", "Flower: Iris", "Bird: Northern mockingbird ",},
{"Texas", "Flower: Bluebonnet sp. ", "Bird: Northern mockingbird "},
{"Utah", "Flower: Sego lily", "Bird: California gull "},
{"Vermont", "Flower: Red clover ", "Bird: Hermit thrush"},
{"Virginia", "Flower: American dogwood", "Bird: Northern cardinal"},
{"Washington", "Flower: Coast rhododendron", "Bird: Willow goldfinch "},
{"West Virginia", "Flower:Rhododendron", "Bird: Northern cardinal "},
{"Wisconsin", "Flower: Wood violet ", "Bird: American robin "},
{"Wyoming", "Flower: Indian paintbrush ", "Bird: Western meadowlark "}};
// While loop to search through array
while(true) {
// Request user input
System.out.println("Enter a state: ");
// Capture user input
String stateName =input.nextLine();
// exit statement
if(stateName.equalsIgnoreCase("None"))
// Exit program
System.exit(0);
else {
// For loop to search through array
for(int row=0,column=0;row<states.length;row++) {
// If statement for matching input string to array data
if(states[row][0].equalsIgnoreCase(stateName)) {
// Print bird information
System.out.println("Bird: " + states[row][column+1]);
// Print Flower information
System.out.println("Flower: " + states[row][column+2] + "n");
} // end if
} // end for
} // end else
} // end while
} // end main
} // end class
Solution
Bug
I ran your code, and got this output:
Enter a state: Indiana Bird: Flower: Peony Flower: Bird: Northern cardinal
So, two things:
1) Your columns are in the wrong order or incorrectly labeled;
2) Your labels are duplicated. They are already in your data (which is unusual) so you could remove the labels from your print clause
System.out.println(states[row][column+1]);
System.out.println(states[row][column+2] + "n");
In a more realistic situation though, very likely the labels would not be included along with the data
Better UI
Your user input is not very intuitive. Take this series of input:
Enter a state:
Boston
Enter a state:
Canada
Enter a state:
42
Enter a state:
None
This should be pretty easy for you to change the code to add a System.out.println("State not found: " + stateName)
that’s reached if the value entered is not found in the array.
Also consider adding this System.out.println("Enter a state: (or None to exit)");
as the way to exit your program is not obvious as it is.
Code comments
I’m not sure whether or not commenting every line of code was a requirement by your teacher, but most programmers would find it very excessive. In production code, you don’t often see code comments (besides language-specific constructs like JavaDoc) as the code should speak for itself as to what it does. You normally only need to add comment if the reasoning behind a certain piece of code is not clear.
These are particularly excessive:
} // end if
} // end for
} // end else
} // end while
} // end main
} // end class
It is actually better in many cases not to declare variables until shortly before you need them. It makes code much more difficult to follow if you have to always look up and down to find variable declarations their usage. It also make it easier to keep variables in the correct scope.
// Begin Scanner for user input later on
Scanner input = new Scanner( System.in );
I’m sure others will find plenty of other things to critique and help you with your code, this is just a start.
Use Enum
Your data set is definitely something I would use an enum for, if not otherwise a csv.
A compact example on what that would look like:
enum States {
AL("Alabama", "Camelia", "Northern Flicker"),
NY("New York", "Rose", "Eastern Bluebird");
private final String name;
private final String flower;
private final String bird;
States(String name, String flower, String bird) {
this.name = name;
this.flower = flower;
this.bird = bird;
}
@Override
public String toString() {
return name;
}
public String initials() {
return name();
}
public String flower() {
return flower;
}
public String bird() {
return bird;
}
}
an example on a way you would use the above:
import java.util.Scanner;
public class Tester {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter a state's name or initials to look for:");
String userSelection = input.nextLine();
// search through the enum
for (States state : States.values()) {
if (userSelection.equalsIgnoreCase(state.toString())
|| userSelection.equalsIgnoreCase(state.initials())) {
System.out.println(
state.toString() + "'s bird is the " + state.bird()
+ " and their flower is: " + state.flower()
);
break;
}
}
/* You can extract the above into a method that returns true or false
and if false tells the user their entry was invalid/doesn't exist */
}
}
Two things come to mind when I see something like this. Both boils down to encapsulation though. The first idea would be to make a State
class that has a Flower, and a Bird property on it. You can then simply make a list of those States and filter appropriately.
static List<U_S_State> usStates;
static {
usStates = new ArrayList<U_S_State>();
usStates.add(new U_S_State("Alabama", "Flower: Camelia", "Bird: Northern flicker"));
}
//pre java 8, comparable needed on U_S_State
public void GetInfo1(String stateName){
int index = usStates.indexOf(new U_S_State(stateName));
if (index == -1){//not found
return;
}
U_S_State state = usStates.get(index);
System.out.println("Bird: " + state.getStateBird());
System.out.println("Flower: " + state.getStateFlower() + "n");
}
//Using java8 stream comparable not needed on U_S_State
public void GetInfo2(String stateName){
if(!usStates.stream().anyMatch(s->s.getStateName()==stateName))
return;
U_S_State state = usStates.stream()
.filter(s->s.getStateName() == stateName)
.findFirst().get();
System.out.println("Bird: " + state.getStateBird());
System.out.println("Flower: " + state.getStateFlower() + "n");
}
public class U_S_State implements Comparable<U_S_State>{
private final String stateFlower;
private final String stateBird;
private final String stateName;
private String stateAbbreviation;
public U_S_State(String stateName){
this(stateName, "", "");
}
public U_S_State(String stateName, String stateFlower, String stateBird) {
this.stateFlower = stateFlower;
this.stateBird = stateBird;
this.stateName = stateName;
}
public String getStateAbbreviation() {
return stateAbbreviation;
}
public void setStateAbbreviation(String stateAbbreviation) {
this.stateAbbreviation = stateAbbreviation;
}
public String getStateName() {
return stateName;
}
public String getStateBird() {
return stateBird;
}
public String getStateFlower() {
return stateFlower;
}
@Override
public int compareTo(U_S_State o) {
return o.stateName.compareTo(this.stateName);
}
}
Mind you this probably isn’t the best choice in names, (or even naming convention) but this does give you and idea of where to go. Making a class that can compare itself to others. We are only interested in comparing the states by their name. implementing Comparable<T>
is important for list as it is how you will search for an item pre java 8. With java 8 you can use stream and lambda’s. Handy if you understand them. That is my suggestion.