Crossover and Mutation functions for Genetic Algorithm
I rewrote parts of your code obtaining an equivalent version with the focus of relying on char arrays instead of String objects to obtain a simpler code. I noticed you use the number 100 in both methods you posted, it could be preferrable declaring a const value like below:

private static final int BOUND = 100;


Your method crossChromosome is structured like the code below:


private String crossChromosome(String m, String f) {
    if (rnd.nextInt(100) &lt; crossRate*100) { 
        //here the body
   }
    else { return (rnd.nextInt(2) == 1) ? f : m; }
    return chrString.toString();
}



You can directly put the else body at the beginning of the method with the negation of the condition like the code below:

private String crossChromosome(String m, String f) {
    if (rnd.nextInt(BOUND) &gt;= crossRate * BOUND) {
        return (rnd.nextInt(2) == 1) ? f : m;
    }

    //here the instructions of the body of your case

    return chrString.toString();
}


You can use char arrays instead of String objects avoiding calls of String methods like the code below:

char[] mArr = m.toCharArray();
char[] fArr = f.toCharArray();
final int mLength = mArr.length;
final int fLength = fArr.length;
final int crossPoint = rnd.nextInt(mLength - 2) + 2;
final int nextCrossPoint = rnd.nextInt(mLength - crossPoint) + crossPoint;


You can rewrite the loop of your method like below:

StringBuilder chrString = new StringBuilder();

for (int i = 0; i &lt; fLength; i++) { 
    boolean condition = (i &lt; crossPoint);

    if (crType != 1 &amp;&amp; !condition) {
        condition = (i &gt;= nextCrossPoint);
    }
    char ch = condition ? fArr[i] : mArr[i];
    chrString.append(ch);
}

return chrString.toString();


Below the code of your method crossChromosome:

private String crossChromosome(String m, String f) {
    if (rnd.nextInt(BOUND) &gt;= crossRate * BOUND) {
        return (rnd.nextInt(2) == 1) ? f : m;
    }

    char[] mArr = m.toCharArray();
    char[] fArr = f.toCharArray();
    final int mLength = mArr.length;
    final int fLength = fArr.length;
    final int crossPoint = rnd.nextInt(mLength - 2) + 2;
    final int nextCrossPoint = rnd.nextInt(mLength - crossPoint) + crossPoint;

    StringBuilder chrString = new StringBuilder();

    for (int i = 0; i &lt; fLength; i++) { 
        boolean condition = (i &lt; crossPoint);

        if (crType != 1 &amp;&amp; !condition) {
            condition = (i &gt;= nextCrossPoint);
        }
        char ch = condition ? fArr[i] : mArr[i];
        chrString.append(ch);
    }

    return chrString.toString();
}


I put condition inside the loop and used the ternary operator.
Same suggestions for the method mutateChromosome, below my version:

private String mutateChromosome(String k) {
    final int mutatRateMulBound = mutatRate * BOUND;
    char[] kArr = k.toCharArray();

    StringBuilder chrString = new StringBuilder();

    for (char c : kArr) { 
        boolean condition = rnd.nextInt(BOUND) &lt; mutatRateMulBound;
        char ch = condition ? options.charAt(rnd.nextInt(27)) : c;
        chrString.append(ch);
    }

    return chrString.toString();
}