Problema com String e Array de String em java

olá, estou tendo um problema com meu código. O objetivo do programa é esse:

Escreva um método que recebe um array de String e uma String como entrada e retorna quantas vezes a String aparece dentro do array.

porém, ele só roda até a linha 27 (a que informa a string que foi digitada para informar o numero de repetições dela dentro do array de string). Aparece a seguinte mensagem: “Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 5
at Consolidacao3.main(Consolidacao3.java:30)”
Queria saber onde estou errando, pois já quebrei muito a cabeça pra tentar descobrir e não consegui ainda. O código:

import java.util.Scanner;

public class Consolidacao3 {

public static void main(String[] args) {

    String[] Arr;

    int i, j;

    Arr = new String[5];

    Scanner entrada = new Scanner(System.in);

    String[] Str;

    Str = new String[1];

    int vezes = 0;

    for (j = 0; j < Str.length; j++) {

        for (i = 0; i < 5; i++) {

            System.out.println("entre com a " + (i + 1) + "ª array de string:");

            Arr[i] = entrada.nextLine();

        }

        System.out.println(

                "o array de strings armazenado é: " + Arr[0] + " " + Arr[1] + " " + Arr[2] + " " + Arr[3] + " "

                        + Arr[4]);

        System.out.println(

                "digite uma string para saber se ela aparecee e quantas vezes no array de strings digitado anteriormente: ");

        Str[j] = entrada.nextLine();

        System.out.println("a string digitada foi: " + Str[j]);

        if (Arr[i].substring(j).startsWith(Str[j])) {

            vezes++;

        }

    }

    System.out.println("A string " + Str[j] + "aparece " + vezes + "vezes no array");

}

}

No trecho abaixo o i será incrementado até 5, que é quando o loop para e seu programa segue.

for (i = 0; i < 5; i++) {

Depois, no trecho abaixo, vc usa o i, cujo valor agora é 5, para acessar um elemento do array e é aqui que a exceção acontece.

if (Arr[i].substring(j).startsWith(Str[j])) {

Não dá para acessar o índice 5 de um array de 5 elementos já que os índices vão de 0 até 4.

Este tipo de situação que vc encontrou é comum quando vc usa variáveis externas para controlar seus loops. O ideal é que vc declare as variáveis no próprio loop, por isso, ao invés de fazer isso:

int i = 0;

for (i = 0; i < 5; i++) {
  // ...
}

Prefira fazer isso:

for (int i = 0; i < 5; i++) {
  // ...
}

Desta forma, cada loop terá sua própria variável de controle e não sofrerá interferência externa.

Seu código corrigido ficou assim:

String[] Arr;

Arr = new String[5];

Scanner entrada = new Scanner(System.in);

String[] Str;

Str = new String[1];

int vezes = 0;

for (int j = 0; j < Str.length; j++) {
  for (int i = 0; i < 5; i++) {
    System.out.println("entre com a " + (i + 1) + "ª array de string:");
    Arr[i] = entrada.nextLine();
  }

  System.out.println(
      "o array de strings armazenado é: " + Arr[0] + " " + Arr[1] + " " + Arr[2] + " " + Arr[3] + " "
          + Arr[4]);

  System.out.println(
      "digite uma string para saber se ela aparecee e quantas vezes no array de strings digitado anteriormente: ");

  Str[j] = entrada.nextLine();

  System.out.println("a string digitada foi: " + Str[j]);

  for (int i = 0; i < 5; i++) {
    if (Arr[i].substring(j).startsWith(Str[j])) {
      vezes++;
    }
  }

  System.out.println("A string " + Str[j] + "aparece " + vezes + "vezes no array");
}

Eu tentei mudar algumas coisas do seu código para ficar mais organizado, olha como ficou:

class Main {
  private static final Scanner entrada = new Scanner(System.in);

  public static void main(String... args) {
    String[] strings = new String[5];
    String stringDesejada;
    int vezes = 0;

    for (int i = 0; i < 5; i++) {
      System.out.printf("Entre com a %dª array de string: ", i + 1);
      strings[i] = entrada.nextLine();
    }

    System.out.println("O array de strings armazenado é: " + Arrays.toString(strings));

    System.out.println("Digite uma string para saber se ela aparece e quantas vezes no array digitado:");

    stringDesejada = entrada.nextLine();

    System.out.println("a string digitada foi: " + stringDesejada);

    for (int i = 0; i < 5; i++) {
      if (strings[i].equals(stringDesejada)) {
        vezes++;
      }
    }

    System.out.printf("A string %s aparece %d vezes no array%n", stringDesejada, vezes);
  }
}

Uma sugestão é que seria legal vc treinar separar sua lógica em métodos para organizar melhor seu programa. Olha só um exemplo:

class Main {
  private static final Scanner entrada = new Scanner(System.in);

  private static String[] pegarArrayDeStrings() {
    String[] strings = new String[5];

    for (int i = 0; i < 5; i++) {
      System.out.printf("Entre com a %dª array de string: ", i + 1);
      strings[i] = entrada.nextLine();
    }

    return strings;
  }

  private static int contarPalavra(String[] strings, String stringDesejada) {
    int vezes = 0;

    for (int i = 0; i < 5; i++) {
      if (strings[i].equals(stringDesejada)) {
        vezes++;
      }
    }

    return vezes;
  }

  public static void main(String... args) {
    String[] strings = pegarArrayDeStrings();

    System.out.println("O array de strings armazenado é: " + Arrays.toString(strings));

    System.out.println("Digite uma string para saber se ela aparece e quantas vezes no array digitado:");

    String stringDesejada = entrada.nextLine();

    System.out.println("a string digitada foi: " + stringDesejada);

    System.out.printf("A string %s aparece %d vezes no array%n", stringDesejada, contarPalavra(strings, stringDesejada));
  }
}

Outra coisa é que seu método de contagem poderia ficar bem simplificado usando Stream, seria assim:

private static long contarPalavraUsandoStream(String[] strings, String stringDesejada) {
  return Stream.of(strings).filter(s -> s.equals(stringDesejada)).count();
}