125

The following code will print 2

String word = "bannanas";
String guess = "n";
int index;
System.out.println( 
    index = word.indexOf(guess)
);

I would like to know how to get all the indexes of "n" ("guess") in the string "bannanas"

The expected result would be: [2,3,5]

Unihedron
  • 10,902
  • 13
  • 62
  • 72
Trufa
  • 39,971
  • 43
  • 126
  • 190

16 Answers16

195

This should print the list of positions without the -1 at the end that Peter Lawrey's solution has had.

int index = word.indexOf(guess);
while (index >= 0) {
    System.out.println(index);
    index = word.indexOf(guess, index + 1);
}

It can also be done as a for loop:

for (int index = word.indexOf(guess);
     index >= 0;
     index = word.indexOf(guess, index + 1))
{
    System.out.println(index);
}

[Note: if guess can be longer than a single character, then it is possible, by analyzing the guess string, to loop through word faster than the above loops do. The benchmark for such an approach is the Boyer-Moore algorithm. However, the conditions that would favor using such an approach do not seem to be present.]

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
31

Try the following (Which does not print -1 at the end now!)

int index = word.indexOf(guess);
while(index >= 0) {
   System.out.println(index);
   index = word.indexOf(guess, index+1);
}
danielbeard
  • 9,120
  • 3
  • 44
  • 58
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    you always print -1 at the end – lukastymo Feb 17 '11 at 20:54
  • @Peter Thank you very much for you answer, it seem to be right, but this is *actually* my first day with Java so I'm a little confused by the final result, this seems to output -1 at the end an I don't quite understand why! thanks!! – Trufa Feb 17 '11 at 20:55
  • @Trufa: It always prints -1 at the end because `indexOf` returns -1 when the character is not found. – ColinD Feb 17 '11 at 21:03
  • @Trufa - the reason it prints `-1` at the end is that the `do` loop executes the body and _then_ discovers that `index == -1` in the terminating `while`. – Ted Hopp Feb 17 '11 at 21:03
  • @ColinD that part I do get, what I don't understand is what is happen with the function for that to happen, it "loops" through the word looking for the occurrence of the character and until that is it can find no more right? and prints this last index of that is the not found (-1), is that what is happening? (I don't know if that came out right) – Trufa Feb 17 '11 at 21:07
  • @Trufa: Yes, it always prints the index before checking whether it's -1. – ColinD Feb 17 '11 at 21:09
14

This can be done in a functional way with Java 9 using regular expression:

Pattern.compile(Pattern.quote(guess)) // sanitize input and create pattern
            .matcher(word) // create matcher
            .results()     // get the MatchResults, Java 9 method
            .map(MatchResult::start) // get the first index
            .collect(Collectors.toList()) // collect found indices into a list
    );

Here's the Kotlin Solution to add this logic as a new a new methods into CharSequence API using extension method:

 // Extension method
fun CharSequence.indicesOf(input: String): List<Int> =
    Regex(Pattern.quote(input)) // build regex
        .findAll(this)          // get the matches
        .map { it.range.first } // get the index
        .toCollection(mutableListOf()) // collect the result as list

// call the methods as
"Banana".indicesOf("a") // [1, 3, 5]
Pavneet_Singh
  • 36,884
  • 5
  • 53
  • 68
9
String string = "bannanas";
ArrayList<Integer> list = new ArrayList<Integer>();
char character = 'n';
for(int i = 0; i < string.length(); i++){
    if(string.charAt(i) == character){
       list.add(i);
    }
}

Result would be used like this :

    for(Integer i : list){
        System.out.println(i);
    }

Or as a array :

list.toArray();
POSIX_ME_HARDER
  • 772
  • 9
  • 22
7

With Java9, one can make use of the iterate(int seed, IntPredicate hasNext,IntUnaryOperator next) as follows:-

List<Integer> indexes = IntStream
          .iterate(word.indexOf(c), index -> index >= 0, index -> word.indexOf(c, index + 1))
          .boxed()
          .collect(Collectors.toList());
System.out.printlnt(indexes);
Naman
  • 27,789
  • 26
  • 218
  • 353
4
int index = -1;
while((index = text.indexOf("on", index + 1)) >= 0) {
   LOG.d("index=" + index);
}
urSus
  • 12,492
  • 12
  • 69
  • 89
3

Java 8+

To find all the indexes of a particular character in a String, one can create an IntStream of all the indexes and filter over it.

import java.util.stream.Collectors;
import java.util.stream.IntStream;
//...
String word = "bannanas";
char search = 'n';
//To get List of indexes:
List<Integer> indexes = IntStream.range(0, word.length())
        .filter(i -> word.charAt(i) == search).boxed()
        .collect(Collectors.toList());
//To get array of indexes:
int[] indexes = IntStream.range(0, word.length())
        .filter(i -> word.charAt(i) == search).toArray();
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
2
String word = "bannanas";

String guess = "n";

String temp = word;

while(temp.indexOf(guess) != -1) {
     int index = temp.indexOf(guess);
     System.out.println(index);
     temp = temp.substring(index + 1);
}
asgs
  • 3,928
  • 6
  • 39
  • 54
2

This is a java 8 solution.

public int[] solution (String s, String subString){
        int initialIndex = s.indexOf(subString);
        List<Integer> indexList = new ArrayList<>();
        while (initialIndex >=0){
            indexList.add(initialIndex);
            initialIndex = s.indexOf(subString, initialIndex+1);
        }
        int [] intA = indexList.stream().mapToInt(i->i).toArray();
        return intA;
    }
Bamidele Alegbe
  • 524
  • 4
  • 7
1
    String input = "GATATATGCG";
    String substring = "G";
    String temp = input;
    String indexOF ="";
    int tempIntex=1;

    while(temp.indexOf(substring) != -1)
    {
        int index = temp.indexOf(substring);
        indexOF +=(index+tempIntex)+" ";
        tempIntex+=(index+1);
        temp = temp.substring(index + 1);
    }
    Log.e("indexOf ","" + indexOF);
idris yıldız
  • 2,097
  • 20
  • 22
1

Also, if u want to find all indexes of a String in a String.

int index = word.indexOf(guess);
while (index >= 0) {
    System.out.println(index);
    index = word.indexOf(guess, index + guess.length());
}
Elite Vip
  • 11
  • 1
  • This is interesting in that it raises an ambiguity in the meaning of "all occurrences". If `guess ` was `"aba"` and `word` was `"ababa"`, it's not clear if the `guess` occurs once or twice in `word`. (I mean, it's clear that one can find `guess` starting at two distinct positions, but since the occurrences overlap it's not clear whether they should both be counted.) This answer takes the view that overlapping occurrences are not counted as distinct. Of course, since OP's wording strongly suggests that `guess` will always have length 1, the ambiguity doesn't arise. – Ted Hopp May 24 '16 at 16:04
1

This can be done by iterating myString and shifting fromIndex parameter in indexOf():

  int currentIndex = 0;

  while (
    myString.indexOf(
      mySubstring,
      currentIndex) >= 0) {

    System.out.println(currentIndex);

    currentIndex++;
  }
Zon
  • 18,610
  • 7
  • 91
  • 99
  • Did you even try running this code? It will print out every position (0, 1, 2, ...) until the index of the last occurrence of `mySubstring`, regardless of whether `mySubstring` can be found at each position. Not at all what OP wanted.. – Ted Hopp May 24 '16 at 16:06
1

I had this problem as well, until I came up with this method.

public static int[] indexesOf(String s, String flag) {
    int flagLen = flag.length();
    String current = s;
    int[] res = new int[s.length()];
    int count = 0;
    int base = 0;
    while(current.contains(flag)) {
        int index = current.indexOf(flag);
        res[count] = index + base;
        base += index + flagLen;
        current = current.substring(current.indexOf(flag) + flagLen, current.length());
        ++ count;
    }
    return Arrays.copyOf(res, count);
}

This method can be used to find indexes of any flag of any length in a string, for example:

public class Main {

    public static void main(String[] args) {
        int[] indexes = indexesOf("Hello, yellow jello", "ll");

        // Prints [2, 9, 16]
        System.out.println(Arrays.toString(indexes));
    }

    public static int[] indexesOf(String s, String flag) {
        int flagLen = flag.length();
        String current = s;
        int[] res = new int[s.length()];
        int count = 0;
        int base = 0;
        while(current.contains(flag)) {
            int index = current.indexOf(flag);
            res[count] = index + base;
            base += index + flagLen;
            current = current.substring(current.indexOf(flag) + flagLen, current.length());
            ++ count;
        }
        return Arrays.copyOf(res, count);
    }
}
Ian S.
  • 1,831
  • 9
  • 17
1

A class for splitting strings I came up with. A short test is provided at the end.

SplitStringUtils.smartSplitToShorterStrings(String str, int maxLen, int maxParts) will split by spaces without breaking words, if possible, and if not, will split by indexes according to maxLen.

Other methods provided to control how it is split: bruteSplitLimit(String str, int maxLen, int maxParts), spaceSplit(String str, int maxLen, int maxParts).

public class SplitStringUtils {

  public static String[] smartSplitToShorterStrings(String str, int maxLen, int maxParts) {
    if (str.length() <= maxLen) {
      return new String[] {str};
    }
    if (str.length() > maxLen*maxParts) {
      return bruteSplitLimit(str, maxLen, maxParts);
    }

    String[] res = spaceSplit(str, maxLen, maxParts);
    if (res != null) {
      return res;
    }

    return bruteSplitLimit(str, maxLen, maxParts);
  }

  public static String[] bruteSplitLimit(String str, int maxLen, int maxParts) {
    String[] bruteArr = bruteSplit(str, maxLen);
    String[] ret = Arrays.stream(bruteArr)
          .limit(maxParts)
          .collect(Collectors.toList())
          .toArray(new String[maxParts]);
    return ret;
  }

  public static String[] bruteSplit(String name, int maxLen) {
    List<String> res = new ArrayList<>();
    int start =0;
    int end = maxLen;
    while (end <= name.length()) {
      String substr = name.substring(start, end);
      res.add(substr);
      start = end;
      end +=maxLen;
    }
    String substr = name.substring(start, name.length());
    res.add(substr);
    return res.toArray(new String[res.size()]);
  }

  public static String[] spaceSplit(String str, int maxLen, int maxParts) {
    List<Integer> spaceIndexes = findSplitPoints(str, ' ');
    List<Integer> goodSplitIndexes = new ArrayList<>();
    int goodIndex = -1; 
    int curPartMax = maxLen;
    for (int i=0; i< spaceIndexes.size(); i++) {
      int idx = spaceIndexes.get(i);
      if (idx < curPartMax) {
        goodIndex = idx;
      } else {
        goodSplitIndexes.add(goodIndex+1);
        curPartMax = goodIndex+1+maxLen;
      }
    }
    if (goodSplitIndexes.get(goodSplitIndexes.size()-1) != str.length()) {
      goodSplitIndexes.add(str.length());
    }
    if (goodSplitIndexes.size()<=maxParts) {
      List<String> res = new ArrayList<>();
      int start = 0;
      for (int i=0; i<goodSplitIndexes.size(); i++) {
        int end = goodSplitIndexes.get(i);
        if (end-start > maxLen) {
          return null;
        }
        res.add(str.substring(start, end));
        start = end;
      }
      return res.toArray(new String[res.size()]);
    }
    return null;
  }


  private static List<Integer> findSplitPoints(String str, char c) {
    List<Integer> list = new ArrayList<Integer>();
    for (int i = 0; i < str.length(); i++) {
      if (str.charAt(i) == c) {
        list.add(i);
      }
    }
    list.add(str.length());
    return list;
  }
}

Simple test code:

  public static void main(String[] args) {
    String [] testStrings = {
        "123",
        "123 123 123 1123 123 123 123 123 123 123",
        "123 54123 5123 513 54w567 3567 e56 73w45 63 567356 735687 4678 4678 u4678 u4678 56rt64w5 6546345",
        "1345678934576235784620957029356723578946",
        "12764444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444",
        "3463356 35673567567 3567 35 3567 35 675 653 673567 777777777777777777777777777777777777777777777777777777777777777777"
    };

    int max = 35;
    int maxparts = 2;


    for (String str : testStrings) {
      System.out.println("TEST\n    |"+str+"|");
      printSplitDetails(max, maxparts);
      String[] res = smartSplitToShorterStrings(str, max, maxparts);
      for (int i=0; i< res.length;i++) {
        System.out.println("  "+i+": "+res[i]);
      }
      System.out.println("===========================================================================================================================================================");
    }

  }

  static void printSplitDetails(int max, int maxparts) {
    System.out.print("  X: ");
    for (int i=0; i<max*maxparts; i++) {
      if (i%max == 0) {
        System.out.print("|");
      } else {
        System.out.print("-");
      }
    }
    System.out.println();
  }
Dariusz
  • 21,561
  • 9
  • 74
  • 114
0

Based on @Pavneet_Singh's answer, a kotlin extension function to return a pair of start and end of the substring, and ignore cases.

fun CharSequence.indicesOf(input: String): List<Pair<Int, Int>> =
Pattern.compile(input, Pattern.CASE_INSENSITIVE).toRegex()
    .findAll(this)
    .map { Pair(it.range.first, it.range.last) }
    .toCollection(mutableListOf())
4shutosh
  • 46
  • 3
-5

Try this

String str = "helloslkhellodjladfjhello";
String findStr = "hello";

System.out.println(StringUtils.countMatches(str, findStr));
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
Vikas Kumbhar
  • 121
  • 12
  • This is good for counting instances of a substring in a larger string, but does not return the indices of the matches. – fiveclubs Jul 15 '15 at 17:11
  • While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Nic3500 Aug 24 '18 at 11:48
  • This does not answer the question. The question require a list of all indices – sheu Jul 30 '20 at 15:52
  • This does not answers question & moreover, There are multiple providers for StringUtils. Which library is used is ambiguous. – Saurabhcdt Jan 14 '21 at 17:11