1

I used many references in the site to build up my program but I'm kind of stuck right now. I think using iterator will do the job. Sadly even though I went through questions which had iterator, I couldn't get the way of using it properly to implement it on my code.

I want to, 1. remove the similar elements found in the list fname 2. count & add the that count of each element found in fname to counter.

Please help me do the above using iterator or with any other method. Following is my code,

List<String> fname = new ArrayList<>(Arrays.asList(fullname.split(""))); //Assigning the string to a list//

    int count = 1;
    ArrayList<Integer> counter = new ArrayList<>();
    List<String> holder = new ArrayList<>();

    for(int element=0; element<=fname.size; element++)
    {
        for(int run=(element+1); run<=fname.size; run++)
        {
            if((fname.get(element)).equals(fname.get(run)))
            {
                count++;
                holder.add(fname.get(run));
            }

            counter.add(count);                    
        }

        holder.add(fname.get(element));
        fname.removeAll(holder);
    }

    System.out.println(fname);
    System.out.println(counter);

Thanks.

Amaani
  • 123
  • 8

4 Answers4

2

From your questions, you basically want to:

1. Eliminate duplicates from given String List

You can simply convert your List to HashSet (it doesn't allow duplicates) and then convert it back to list (if you want the end result to be a List so you can do something else with it...)

2. Count all occurences of unique words in your list The fastest coding is to use Java 8 Streams (code borrowed frome here: How to count the number of occurrences of an element in a List)

Complete code

public static void main(String[] args) {
    String fullname = "a b c d a b c"; //something
    List<String> fname = new ArrayList<>(Arrays.asList(fullname.split(" ")));

    // Convert input to Set, and then back to List (your program output)
    Set<String> uniqueNames = new HashSet<>(fname);
    List<String> uniqueNamesInList = new ArrayList<>(uniqueNames);
    System.out.println(uniqueNamesInList);

    // Collects (reduces) your list
    Map<String, Long> counts = fname.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    System.out.println(counts);
}
xanmcgregor
  • 372
  • 2
  • 13
  • You can extract the uniqueNames directly from the Map with keySet(). – Guillaume F. Jul 09 '17 at 14:20
  • @GuillaumeF. it's a `HashSet`, not a `HashMap`. Are you sure you can do that? – MiguelKVidal Jul 09 '17 at 15:15
  • @MiguelKVidal `Set uniqueNames = counts.keySet();` Also the List conversion is not useful, both are Collections. – Guillaume F. Jul 09 '17 at 18:37
  • @GuillaumeF. I checked the docs and haven't found this method in the Set interface: https://docs.oracle.com/javase/8/docs/api/java/util/Set.html. Are you really sure your aren't talking about the Map interface (https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#keySet--)? – MiguelKVidal Jul 09 '17 at 18:48
  • @MiguelKVidal read my comment carefully, and see that I am referring to the variable `counts` which is a `Map`. – Guillaume F. Jul 09 '17 at 18:58
  • @GuillaumeF. now I see it! Sorry, it was my mistake. – MiguelKVidal Jul 09 '17 at 20:55
0

You can try something like this:

Set<String> mySet = new HashSet<>();
mySet.addAll( fname ); // Now you have unique values

for(String s : mySet) {
    count = 0;
    for(String x : fname) {
        if( s.equals(x) ) { count++; }
    }
    counter.add( count );
}

This way we don't have a specific order. But I hope it helps.

In Java 8, there's a one-liner:

List<Integer> result = fname
    .stream()
    .collect(Collectors.groupingBy(s -> s))
    .entrySet()
    .stream()
    .map(e -> e.getValue().size())
    .collect(Collectors.toList());
MiguelKVidal
  • 1,498
  • 1
  • 15
  • 23
0

I do not think that you need iterators here. However, there are many other possible solutions you could use, like recursion. Nevertheless, I have just modified your code as the following:

    final List<String> fname = new ArrayList<String>(Arrays.asList(fullname.split("")));
    // defining a list that will hold the unique elements.
    final List<String> resultList = new ArrayList<>();
    // defining a list that will hold the number of replication for every item in the fname list; the order here is same to the order in resultList
    final ArrayList<Integer> counter = new ArrayList<>();

    for (int element = 0; element < fname.size(); element++) {
        int count = 1;
        for (int run = (element + 1); run < fname.size(); run++) {
            if ((fname.get(element)).equals(fname.get(run))) {
                count++;
                // we remove the element that has been already counted and return the index one step back to start counting over.
                fname.remove(run--);
            }
        }
        // we add the element to the resulted list and counter of that element
        counter.add(count);
        resultList.add(fname.get(element));
    }
    // here we print out both lists.
    System.out.println(resultList);
    System.out.println(counter);

Assuming String fullname = "StringOfSomeStaff"; the output will be as the following:

[S, t, r, i, n, g, O, f, o, m, e, a]
[3, 2, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1]
Kh.Taheri
  • 946
  • 1
  • 10
  • 25
  • I want something like, if {s, t, r, i, n, g, o, f, s, o, m, e, s, t, a, f, f} is entered it should generate the count list as {3, 2, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1} which is as, No. of s=3, t=2, r=1, i=1 etc. The counting of the elemrnts should be done as per their order in th list & the counted elements should be removed as soon as they are counted. – Amaani Jul 09 '17 at 14:30
  • I think I did it as you said.. I don't remove the counted element but I don't count it again; its counted only once. – Kh.Taheri Jul 09 '17 at 14:54
  • 1
    Ok thanks. I still didn't try out the code. I'll let you know the result as soon as I check with it. – Amaani Jul 10 '17 at 06:43
  • Sorry but I tried out the code & it do count the elements repeatedly. Just check with your example, at first under 'S' it has no. 3, again in the middle under 'S' it has no. 2. I counts the no. of remaining similar elements again when it come across a previously counted element if it's not deleted. – Amaani Jul 10 '17 at 13:07
  • @Amaani .. I now understand what you really want; I have updated the code, check it once again. – Kh.Taheri Jul 10 '17 at 13:59
  • Sorry but now it gives 2 blank lists as the output. – Amaani Jul 10 '17 at 14:11
  • I have just tried it here .. did you copy all the code? – Kh.Taheri Jul 10 '17 at 14:13
  • I'm really really sorry. Last time I have copied your code without 2 lines. (Crazy me). It works 100% in the way I want. Thanks a lot. – Amaani Jul 10 '17 at 14:20
  • Good! .. thats mean you will mark my answer as the correct answer! ;) – Kh.Taheri Jul 10 '17 at 14:22
  • Sure. Can you please add comments to explain your code. It'll help me a lot as I'm just a beginner. – Amaani Jul 10 '17 at 14:23
  • 1
    Sorry but I don't have enough reputations to upvote :( – Amaani Jul 10 '17 at 14:38
  • Its Okay, I am just enjoying collecting credits. I just up-voted your question .. Good luck :) – Kh.Taheri Jul 10 '17 at 15:01
  • Thanks and Good Luck to you too. :) – Amaani Jul 10 '17 at 16:23
0

I was using LinkedHashMap to preserve order of elements. Also for loop, which I am using, implicitly uses Iterator. Code example is using Map.merge method, which is available since Java 8.

    List<String> fname = new ArrayList<>(Arrays.asList(fullname.split("")));
    /*
        Create Map which will contain pairs kay=values
        (in this case key is a name and value is the counter).
        Here we are using LinkedHashMap (instead of common HashMap)
        to preserve order in which name occurs first time in the list.
    */
    Map<String, Integer> countByName = new LinkedHashMap<>();
    for (String name : fname) {
        /*
             'merge' method put the key into the map (first parameter 'name').
             Second parameter is a value which we that to associate with the key
             Last (3rd) parameter is a function which will merge two values
             (new and ald) if map already contains this key
         */
        countByName.merge(name, 1, Integer::sum);
    }
    System.out.println(fname);                  // original list [a, d, e, a, a, f, t, d]
    System.out.println(countByName.values());   // counts [3, 2, 1, 1, 1]
    System.out.println(countByName.keySet());   // unique names [a, d, e, f, t]

Also same might be done using Stream API but it would be probably hard for understanding if you are not familiar with Streams.

    Map<String, Long> countByName = fname.stream()
            .collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()));
Artem Petrov
  • 772
  • 4
  • 17
  • Thank you very much. I tried it on my code & it worked exactly as I wanted. This is the first time that I came across this `Map` function. Thanks a lot. Please add comment lines describing the 2nd to 4th lines if you can so that I can clearly get what it does. – Amaani Jul 10 '17 at 13:13