How to return multiple conditions? - java

What should be my return at the end of my for loop? I'm trying to display the added results of all three parties numDemocrat, numRepulican and numIndepent by
calculating and then printing the number of democrats (party is "D"),
republicans (party is "R"), and independents (party is anything else).
I'm currently looping over the MemberOfCongress ArrayList returned by parseMembersOfCongress and counting up how many of each party type there are.
Also in my loop I need to check which party the current member belongs to and increment the proper variable. After the loop completes I then print the totals.
public void printPartyBreakdownInSenate()
{
CongressDataFetcher.fetchSenateData(congressNum);
}
{
ArrayList<MemberOfCongress> parseMembersOfCongress; String jsonString;
}
{
System.out.println("Number of Members of the Senate of the " + "&congressNum=" + "?chamber=");
}
public String[]
{
int numDemocrats = 0;
int numRepblican = 0;
int numIndepent = 0;
ArrayList<MemberOfCongress> members;
for (MemberOfCongress memberParty : members) {
if (memberParty.getParty() == "D" ) {
numDemocrats++;
}
else if (memberParty.getParty() == "R" ){
numRepblican++;
}
else if (memberParty.getParty() == "null"){
numIndepent++;
}
}
return ???;
}

Firstly i'm 99% positive you cannot return multiple values, unless your return either an array, an array list or a map.
But what you could do as a work around is one of the following.
1). Return a String array of party members.
2). Return a 2D array mapping name to age or something similar.
3). Return a hashmap of the data with a custom class of information mapped to a name.
4). Use getters to get different pieces of the data at time or all at once.

Java (like the majority of programmming languages) allows only a single return value from a method. There are lots of good reasons for this.
If you need to return multiple values then you will need a separate class for which your method can return a reference to an instance.
For example, in your case:
public enum Party {
REPUBLICAN, DEMOCRAT, OTHER;
}
public Map<Party, Integer> senatorsByParty(List<MemberOfCongress> senators) {
return senators.stream()
.collect(Collectors.groupingBy(MemberOfCongress::getParty, Collectors.counting()));
}
Apologies if you are not aware of the Java 8 syntax here. The stream functions are really just saying 'take all the senators, group them by party and then count them'. The key point is that you are returning a map from parties to integers representing the count of senators.

Related

Returning the index of a String parameter in an array

While I know that this code should work to return the index, for some reason it's skipping the if statement and going straight to the else, when I know that the name is within the array, with the array that I'm using for testing. Won't even print the "if - reading" line.
public int find(String name)
{
int index = 0;
for(int i = 0; i < this.shoppingItems.length;i++)
{
if(this.shoppingItems[i].equals(name))
{
System.out.println("If - Reading");
index = i;
}
else
{
index = -1;
}
}
System.out.println(index);
return index;
}
//Main
ShoppingItem[] items = new ShoppingItem[]{new ShoppingItem("Eggs",3.2),new ShoppingItem("Bread",2.8),new ShoppingItem("Bacon",9),new ShoppingItem("Peas",2),new ShoppingItem("Spinach",4),new ShoppingItem("Chocolate",8)};
ShoppingList itemList = new ShoppingList(items);
itemList.find("Bread");
"While I know that this code should work to return the index, for some reason it's skipping the if statement and going straight to the else"
Stop! Java is not wrong; your code is, and it shouldn't work. Your if statement is not being skipped; it's just that the condition is always false, because this.shoppingItems[i] is a ShoppingItem object, and you are comparing it with name, which is a string. A ShoppingItem object is never equal to a string.
Presumably, what you want to test is whether the ShoppingItem object's name is equal to that string. Presumably, your class has a getName method, so you should test:
if(this.shoppingItems[i].getName().equals(name)) {
// ...
}
This is a common kind of programming error, perhaps because it's often acceptable in natural language to say one thing when you mean something closely related; e.g. you might say "I asked the help desk" when really you asked a person at the help desk, you did not ask the desk itself. This is a bit like that; you want the item's name to equal name, not the item itself.
Unless you are compelled to use arrays, you can make things much easier by using lists. They have quite a few useful features.
List<String> items = List.of("bread", "juice", "eggs", "milk");
System.out.println(find("eggs"));
System.out.println(find("butter"));
public int find(String name) {
return items.indexOf(name);
}
Prints
2
-1
That method of the List interface pretty much negates the need to write you own method. I just did it for demonstration purposes.
This example was using a List of Strings and not ShoppingItem class. You could get a List<ShoppingItem> to work by overriding the equals method in your class (something you should get in the habit of anyway).
And here is a taste of how would do it with Stream (java 8+). It presumes list is a simple array of ShoppingItem.
public int find(String name) {
return IntStream.range(0, list.length).filter(
i -> list[i].item.equalsIgnoreCase(name)).findFirst().orElse(-1);
}

An efficient way to store collections of unique enums with data

In my current setup I'm storing my categorical enum (Defense) and value (Rank, also an enum) in a wrapper object.
public class RankedDefense implements Serializable {
private Defense defense;
private Rank rank;
public RankedDefense(Defense d, Rank r) {
defense = d;
rank = r;
}
public Defense getDefense() {
return defense;
}
public Rank getRank() {
return rank;
}
}
I then store lists of these in a data object (ScoutData). The same Defense will never be repeated in any of these lists.
The problem arises when I implement methods to organize the data from multiple ScoutData objects. I need to merge multiple lists of RankedDefenses while making sure that the same Defense is never repeated.
The only efficient way I found to do this was to repeatedly iterate over both lists and check. However, I'm not confident the method I used even works properly.
List<RankedDefense> defenses = new ArrayList<>();
for (ScoutData d : data) {
//We need to compare every item in every list
for (RankedDefense potential : d.getTeleopListDefensesBreached()) {
for (RankedDefense listItem : defenses) {
if (listItem.getDefense() == potential.getDefense()) {
defenses.add(new RankedDefense(listItem.getDefense(), Rank.NOT_ATTEMPTED)); //TODO actually average the ranks
break;
}
}
}
}
return defenses;
I can't seem to figure out where to put the line of code that adds the RankedDefense if one with the same Defense isn't already in the list.
Is there a more efficient method to store my values that would prevent this iteration headache? And if not, is there a more readable and reliable way to implement the iteration code?
Using EnumMap and changing my code accordingly has solved all my problems. It does exactly what I was looking for.

Increment each object's value by 11 inside a list

I have a list of objects where list name is employments and it has 'n' number of objects called employments.Each employment object has variable called serialnumber. Now i need to increment serialnumber for each object by 11.
Here is code
for(Employment employment:employments.getEmployemnts()){
if(employment="GENERAL_MANAGER"){
employement.setSerialNumberForGenManager()
}else{
employment.setSerialNumberForOthers()
}
Inside the employment class:
public static employemntIndex=11;
public employemnt setSerialNumberForGenManager(){
this.serialNumber = 0;
}
public employemnt setSerialNumberForOthers(){
this.serialNumber = employemntIndex+serialNumber;
}
Now,i'm not able to increment values by 11. The result for every object is always 11 only.It is not getting incremented.
This may be because of your String comparison. String comparisons should use the Object#equals(Object) method (as opposed to ==);
if (yourString.equals("COMPARISON STRING")) //do stuff
This is because String is an instance (which happens to contain text), and the the == operator in this case only tests the references, not whether the instances themselves contain the same text.
Also, = is an assignment operator, == should be used for most comparisons (other than 'special cases', such as comparing Strings).
The next problem is that you are not carrying the values over (as you say). To fix this;
public static employemntIndex = 11;
//Increase the employment index for each GENERAL_MANAGER
public employemnt setSerialNumberForOthers(){
this.serialNumber = employmentIndex;
employmentIndex += 11;
}
Try like this
public static Integer employemntIndex = 0;
public employemnt setSerialNumberForOthers(){
this.serialNumber = employemntIndex;
employemntIndex += 11;
}
Two possible errors:
You are using a so called "enhanced for loop".
You can't edit the elements of a collection that way as that loop is read-only.
To edit elements you have to use a for loop with an explicit iteration index or an iterator.
You seem to be comparing a reference (memory address with a String that is unlikely to correspond to a memory address.
employment="GENERAL_MANAGER"
You probably forgot to call a getter method like
employment.getRole().equals("GENERAL_MANAGER")
So it would be (if size() method is not supported you should use array.length)
for(int i = 0; i < employments.getEmployemnts().size(); i++) {
if(employments[i].yourGetter().equals("GENERAL_MANAGER")){
employements[i].setSerialNumberForGenManager()
}else{
employments[i].setSerialNumberForOthers()
}
Or if your collection implements the List interface
Iterator iter = employments.getEmployments().iterator();
while (iter.hasNext()){
Employment employment = iter.next();
if(employment.yourGetter().equals("GENERAL_MANAGER")){
employement.setSerialNumberForGenManager()
}else{
employment.setSerialNumberForOthers()
}
}
Hope that helped
Edit:
as KookieMonster has noticed you are using the assignment operator within the IF condition you should use the equals method

Android II JAVA Sorting An ArrayList of an object

First of all sorry if my English bad, its not my first language..
I'm working on and android app project, that needed to sort ArrayList of an object..so I made this method to deal with that...
Lets say that I have an object of Restaurant that will contain this data:
private String name;
private float distance ;
And I sort it using the value of the variable distance from lowest to highest:
public void sort(RArrayList<RestaurantData> datas) {
RestaurantData tmp = new RestaurantData();
int swapped;
boolean b = true;
while (b) {
swapped = 0;
for (int i = 0; i < datas.size()-1; i++) {
if (datas.get(i).getDistance() > datas.get(i+1).getDistance()) {
tmp = datas.get(i);
datas.set(i, datas.get(i+1));
datas.set(i+1, tmp);
swapped = 1;
System.err.println("Swapped happening");
}
}
if (swapped == 0) {
System.err.println("Swapped end");
break;
}
}
But when i try the program..the result of an ArrayList is still random, is there any problem with my logic to sort the ArrayList of an object..
Please Help...Thankyou..
Why not use the Collections.sort method?
Here's how you could do it in your project:
public void sort(RArrayList<RestaurantData> datas) {
Collections.sort(datas, new Comparator<RestaurantData>() {
#Override
public int compare(RestaurantData lhs, RestaurantData rhs) {
return lhs.getDistance() - rhs.getDistance();
}
});
}
The above solution is a bit "destructive" in the sense that it changes the order of the elements in the original array - datas. If that's fine for you go ahead and use it. Personally I prefer things less destructive and if you have the memory to spare (meaning your array is small) you could consider this solution which copies the array before sorting. It also assumes your RArrayList is an implementation of ArrayList or backed up by it:
public List<RestaurantData> sort(RArrayList<RestaurantData> datas) {
// Create a list with enough capacity for all elements
List<RestaurantData> newList = new RArrayList<RestaurantData>(datas.size());
Collections.copy(newList, datas);
Collections.sort(newList, new Comparator<RestaurantData>() {
#Override
public int compare(RestaurantData lhs, RestaurantData rhs) {
return lhs.getDistance() - rhs.getDistance();
}
});
return newList;
}
Another thing to consider is also to create a single instance of the Comparator used in the method, since this implementation will create one instance per call. Not sure if it's worth it though, because it will also be destroyed quite soon since the scope is local.
Here's the documentation for the Collections api
One last thing, the comparator simply needs to return a value less than 0 if the elements are in the right order, bigger than 0 if they're in the wrong order or 0 if they're the same. Therefore it seems to be that it's enough to simply subtract the distances of each restaurant. However, if this isn't the case, please implement the comparator suiting your needs.

Loop for Enums in Java

I have some enums like this:
public enum Classification {
UNKNOWN("Unknown"),
DELETION("Deletion"),
DUPLICATION("Duplication"), ....
but some of them have like 20 members, so currently in code I deal with them with huge if/else blocks like this:
int classification= rs.getInt("classification");
if (classification == Classification.UNKNOWN.ordinal()) {
variant.setClassification(Classification.UNKNOWN);
} else if (classification == Classification.DELETION.ordinal()) {
variant.setClassification(Classification.DELETION);
( rs is from JDBC tho).
Does Java have a better way this these big if/else blocks to do what I am doing? some sorting of looping through it?
You could use Enum#values() to get all enum values in an array. The ordinal maps 1:1 to the array index. Add the following method fo your Classification enum:
public static Classification of(int ordinal) {
if (0 <= ordinal && ordinal < values().length) {
return values()[ordinal];
}
throw new IllegalArgumentException("Invalid ordinal " + ordinal);
}
and use it as follows
Classification classification = Classification.of(rs.getInt("classification"));
// ...
However, using enum's ordinal for this is not the best practice. What if some developer rearranges the enum's values or adds/removes values? Even the javadoc warns that it has usually no use for developers. Rather give each enum value a fixed identifier. You could pass it in as an additional argument of the enum constructor argument. You could even use enum's String representation for that.
UNKNOWN(1, "Unknown"),
DELETION(2, "Deletion"),
DUPLICATION(3, "Duplication"),
// ...
Then use that value for DB instead and modify the of() method to walk through them in a foreach loop:
public static Classification of(int id) {
for (Classification classification : values()) {
if (classification.id == id) {
return classification;
}
}
throw new IllegalArgumentException("Invalid id " + id);
}
If the db value is the ordinal of the Enum then:
int classification= rs.getInt("classification");
variant.setClassification(Classification.values()[classification]);
I'll leave bounds checking as an exercise for the reader.
You can loop through an enumeration’s values via the object the someEnum.values() method returns:
for (Classification clz : Classification.values()) doSomethingWith(clz);
found here
I don’t know how exactly I can help you, since i don’t know what rs.getInt(String) does.
It seems to give back an Integer representing a enum value of Classification, but why?
Use variant.setClassification(YourEnumClassHere.values()[classification]). Enum.values() returns an array of all the declared enums in that class.
Instead of storing ordinal, you can store the name and use the valueOf method to convert the String back to your Enum type.
If you willing and able to store a string representation (this is a good technique) of the ENUM in your database, see Reference from Gareth Davis in comments above. If you are unwilling and/or unable to store a string representation and must continue with an ordinal representation, I suggest that a Map is called for. Here is some example code:
public class EnumMap
{
private enum FistSounds
{
Blam, Kapow, Zowie, Biff;
private static Map<Integer, FistSounds> ordinalMap = new HashMap<Integer, FistSounds>();
static
{
ordinalMap.put(Blam.ordinal(), Blam);
ordinalMap.put(Kapow.ordinal(), Kapow);
ordinalMap.put(Zowie.ordinal(), Zowie);
ordinalMap.put(Biff.ordinal(), Biff);
}
public static final FistSounds getByOrdinal(final int enumIndex)
{
return ordinalMap.get(enumIndex);
}
}
public static void main(String[] args)
{
FistSounds fistSound;
for (int index = -1; index < 5; ++index)
{
fistSound = FistSounds.getByOrdinal(index);
System.out.print("Ordinal: ");
System.out.print(index);
System.out.print(", FistSound: ");
System.out.println(fistSound);
}
}
}
I'd recommend using a switch statement, if the logic to execute is different for each case....
do as #Gareth Davis instructs and then just have a switch statement and handle each case as required.
Enums are also eligible to be used in switch statements see here

Categories