5

I have this code, to find the number of female artists, male artists, or bands -

 import java.util.*;


 public class FindGender {


    public static void main(String[] args) {
        // TODO code application logic here
        ArrayList < String > artists = new ArrayList < > ();
        int mnum = 0, fnum = 0, bnum = 0;
        artists.add("Beyonce (f)");
        artists.add("Drake (m)");
        artists.add("Madonna (f)");
        artists.add("Michael Jackson (m)");
        artists.add("Porcupine Tree (b)");
        artists.add("Opeth (b)");
        artists.add("FallOut Boy (b)");
        artists.add("Rick Ross {m}");
        artists.add("Chris Brown (m)");
        if (artists.contains("(b)")) bnum++;
        if (artists.contains("(m)")) mnum++;
        if (artists.contains("(f)")) fnum++;
        System.out.println("The number of male artists is: " + mnum);
        System.out.println("The number of female artists is: " + fnum);
        System.out.println("The number of bands is: " + bnum);
    }

 }

But the output shows - run:

The number of male artists is: 0
The number of female artists is: 0
The number of bands is: 0
BUILD SUCCESSFUL (total time: 0 seconds)

Any help would be appreciated

singhakash
  • 7,891
  • 6
  • 31
  • 65

6 Answers6

6

Contains and containing a part of a String are different. In order to return true, it should match to the whole String.

This works

for (String item : artists) {
        if (item.contains("(b)")) bnum++;
        if (item.contains("(m)")) mnum++;
        if (item.contains("(f)")) fnum++;    
}
Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
6

list#contains() compares the whole string in the list rather than part of string instead you can do

if(artists.stream().anyMatch(e -> e.contains("(b)")))   // java 8 solution

i.e. iterating over the list and checking contains on elements of list.

singhakash
  • 7,891
  • 6
  • 31
  • 65
2

You could use something like if(string.indexOf("(f)")!=-1) fnum++. This would look like this in your code.

public static void main(String[] args) 
{
    // TODO code application logic here
    ArrayList<String> artists = new ArrayList<>();
    int mnum = 0, fnum = 0, bnum = 0;
    artists.add("Beyonce (f)");
    artists.add("Drake (m)");
    artists.add("Madonna (f)");
    artists.add("Michael Jackson (m)");
    artists.add("Porcupine Tree (b)");
    artists.add("Opeth (b)");
    artists.add("FallOut Boy (b)");
    artists.add("Rick Ross (m)");
    artists.add("Chris Brown (m)");

    for(String s:artists)
    {
        if(s.indexOf("(b)")!=-1) bnum++;
        if(s.indexOf("(m)")!=-1) mnum++;
        if(s.indexOf("(f)")!=-1) fnum++;
    }

    System.out.println("The number of male artists is: " + mnum);
    System.out.println("The number of female artists is: " + fnum);
    System.out.println("The number of bands is: " + bnum);
}
Dan
  • 7,286
  • 6
  • 49
  • 114
0

This can easily be done with Java 8 streams:

long numberOfMaleArtists = artists.stream()
    .filter(artist -> artist.contains(("(m)")))
    .count();

This would create a stream from the artists list, and filter out only the male artists. It then counts the occurences.

Preferably, this can be refactored into an own method which takes the text to filter as input. You could then filter artists by name or whatever is wanted.

Magnilex
  • 11,584
  • 9
  • 62
  • 84
0

You are using the contain method on the whole List, you should use it on each element.

In your case, you can use a for each loop, as shown in the example below.

for(String artist : artists) {
    if (artist.contains("(b)")) bnum++;
        if (artist.contains("(m)")) mnum++;
        if (artist.contains("(f)")) fnum++;

}
Dan
  • 7,286
  • 6
  • 49
  • 114
uncleBounty
  • 673
  • 8
  • 14
0

The main problem is that the contains-method on the ArrayList checks for an exact match of the String, not a part of the String. Instead, each String in the List must be checked using String.contains.

If you are using Java 8, one approach is to collect the ArrayList to a Map and use reduction for counting occurrences. Assume that you create a separate function for checking the "type", like this:

private static String artistType(final String artist) {
    if (artist.contains("(b)")) {
        return "band";
    } else if (artist.contains("(m)")) {
        return "male";
    } else if (artist.contains("(f)")) {
        return "female";
    }
    return "unknown";
}

It uses the contains-method to determine the type of artist.

Then, you can use a combination of collectors and reduction to count all occurances.

 Map<String, Integer> countByType = artists.stream()
      .collect(Collectors.groupingBy(
              FindGender::artistType,
              Collectors.reducing(0, i -> 1, Integer::sum)));

The resulting map will contain the keys band, male and female – the values will be 3, 4, 2 as in the OPs example.

The full example looks like this:

public class FindGender {
    public static void main(String[] args) {
        List<String> artists = new ArrayList<>();

        artists.add("Beyonce (f)");
        artists.add("Drake (m)");
        artists.add("Madonna (f)");
        artists.add("Michael Jackson (m)");
        artists.add("Porcupine Tree (b)");
        artists.add("Opeth (b)");
        artists.add("FallOut Boy (b)");
        artists.add("Rick Ross (m)");
        artists.add("Chris Brown (m)");


        Map<String, Integer> countByType = artists.stream()
                .collect(Collectors.groupingBy(
                        FindGender::artistType,
                        Collectors.reducing(0, i -> 1, Integer::sum)));

        System.out.println("Map: " + countByType);
    }

    private static String artistType(final String artist) {
        if (artist.contains("(b)")) {
            return "band";
        } else if (artist.contains("(m)")) {
            return "male";
        } else if (artist.contains("(f)")) {
            return "female";
        }
        return "unknown";
    }
}

And the output is: Map: {band=3, female=2, male=4}

wassgren
  • 18,651
  • 6
  • 63
  • 77