Hide certain email characters Hide email characters:

When email only has one letter then just cover that letter with the * symbol e.g. *@gmail.com

When email has two letters then cover second letter with the symbol * e.g. t*@gmail.com

When email has three letters then cover second and third with the symbol * e.g. t**gmail.com

When email has four or more letters then show first three letters and add 4 stars at the ends - e.g.
tim****@gmail.com
tom****@gmail.com



My code works but I feel like its way too much hard-coding and can be done much cleaner
public static String hideSomeOfEmailValue(String privateEmail) {
StringBuilder stringBuilder = new StringBuilder(privateEmail);
int atSignIndex = privateEmail.indexOf(&quot;@&quot;);
String emailName = privateEmail.substring(0, atSignIndex);

if (emailName.length() == 1) {
    return stringBuilder.replace(0, emailName.length(), &quot;*&quot;).toString();
}
if (emailName.length() &gt; 1 &amp;&amp; emailName.length() &lt; 4) {
    return stringBuilder.replace(1, atSignIndex, StringUtils.repeat(&quot;*&quot;, emailName.length() - 1)).toString();
} else {
    stringBuilder = new StringBuilder(privateEmail.substring(0, 2));
    String emailProvider = privateEmail.substring(atSignIndex);
    stringBuilder.append(&quot;****&quot;).append(emailProvider);
    return stringBuilder.toString();
}


locate at what index at sign located
trim  everything until at sign which gives us name of the email only so we can easily.
Bugs:

privateEmail.substring(0, 2) needs to change to privateEmail.substring(0, 3) in the else, since end index is exclusive and we want to include 3 characters, not 2.

Method assumes that privateEmail contains a &quot;@&quot;, and does not check if atSignIndex results in -1, resulting in a StringIndexOutOfBoundsException if there is no &quot;@&quot;. Return privateEmail (with no hiding applied) early if you expect this method be handed any generic string which could potentially be an email, or throw an IllegalArgumentException if privateEmail is always expected to be an email. I consider the latter to be better design. Note that both these situations handle empty strings as well.


Improvements:

Use var for type inference where the type is obvious from the right side, like new StringBuilder(...), or String#substring. This is as of Java 10.

1 &lt; emailName.length() is redundant because length of 0 and 1 are handled by earlier cases.

StringUtils.repeat can be replaced with String#repeat as of Java 11. Rids of need for external dependency here.

Instantiating a new StringBuilder in the else can be replaced with mutating the current one, namely with the delete and insert instance methods.

Move stringBuilder declaration lower, to only when it is needed.

Replace &quot;*&quot; with a static final variable, such that we could change it to &quot;-&quot; or &quot;_&quot; down the road and remain consistent across all the ifs and the else. This, despite being a character, will have to be a String to remain type-compatible with String#repeat and StringBuilder#replace.
Final code:


private static final String HIDE_CHAR = &quot;*&quot;;

public static String asHiddenEmail(String privateEmail) {
    int atSignIndex = privateEmail.indexOf(&quot;@&quot;);

    if (atSignIndex == -1) {
        throw new IllegalArgumentException(&quot;`privateEmail` must be an email.&quot;);
    }

    var stringBuilder = new StringBuilder(privateEmail);
    var emailName = privateEmail.substring(0, atSignIndex);

    if (emailName.length() == 1) {
        return stringBuilder.replace(0, emailName.length(), HIDE_CHAR).toString();
    }
    if (emailName.length() &lt; 4) {
        var hiddenNameEnd = HIDE_CHAR.repeat(emailName.length() - 1);
        return stringBuilder.replace(1, atSignIndex, hiddenNameEnd).toString();
    }
    else {
        stringBuilder.delete(3, atSignIndex);
        stringBuilder.insert(3, HIDE_CHAR.repeat(4));
        return stringBuilder.toString();
    }
}