0
import java.util.*;

char[] characterArray1 = {'D', 'B', 'C', 'A', 'B', 'A'};
char[] characterArray2 = {'D', 'B', 'C', 'A', 'E', 'T'};
System.out.println(FRC(characterArray2));

public static char FRC(char[] array) {
        HashMap<Character, Integer> hashMap = new HashMap<Character, Integer>();
        for(char character: array) {
                if(hashMap.containsKey(character)) {
                        return character;
                }else {
                        hashMap.put(character, 1);
                }
        }return null
}

characterArray1 is able to return character 'B' as it is the first recurring character

So how am I able to return null from a character returning method when I use characterArray2 as the argument?

2
  • If you were able to return null (you can't), you would need to test whether the method returned null. In the same way, you can test whether it returned 0 (i.e. '\0') Commented Sep 25, 2021 at 15:14
  • Why use a Map if you're going to return immediately upon finding the duplicate? Just use a Set. Commented Sep 25, 2021 at 15:18

3 Answers 3

1

If you need to return null, you need to make the return type the primitive wrapper type, Character.

Also, there is no obvious need to use a Map here: use a Set, and use the return value of Set.add as an indicator that the character was seen before:

public static Character FRC(char[] array) {
  Set<Character> seen = new HashSet<>();
  for (Character c : array) {
    if (!seen.add(c)) {
      return c;
    }
  }
  return null;
}
Sign up to request clarification or add additional context in comments.

Comments

0

You need to use Character which wraps a value of the primitive type char in an object.

public static Character FRC(char[] array) {
        HashMap<Character, Integer> hashMap = new HashMap<Character, Integer>();
        for(char character: array) {
                if(hashMap.containsKey(character)) {
                        return character;
                }else {
                        hashMap.put(character, 1);
                }
        }
        return null;
}

Comments

0

As the correct Answer by Andy Turner said, use a Set for tracking individual objects rather than a Map for pairs of objects.

Code point

The char type (and its wrapper class Character) is legacy, and is essentially broken. As a 16-bit value, it is not capable of representing most characters.

Instead, use code point integer numbers.

public static String firstRecurringCharacter ( List < String > inputs )
{
    Objects.requireNonNull( inputs );
    Set < Integer > seen = new HashSet <>();
    for ( String s : inputs )
    {
        Objects.requireNonNull( s , "Input of list of String objects contained a null." );
        if ( s.length() != 1) throw new IllegalStateException( "Input of list of String objects contained an element with other than one character." );
        if ( ! seen.add( s.codePointAt( 0 ) ) )
        {
            return s;
        }
    }
    return null;
}

Usage.

List < String > inputX = List.of( "D" , "B" , "C" , "A" , "B" , "A" );
List < String > inputY = List.of( "D" , "B" , "C" , "A" , "E" , "T" );

System.out.println( App5.firstRecurringCharacter( inputX ) );
System.out.println( App5.firstRecurringCharacter( inputY ) );

When run.

B

null

Optional

Returning null as a legitimate value is problematic. In such a case, use an Optional wrapper.

public static Optional < String > firstRecurringCharacter ( List < String > inputs )
{
    Objects.requireNonNull( inputs );
    Set < Integer > seen = new HashSet <>();
    for ( String s : inputs )
    {
        Objects.requireNonNull( s , "Input of list of String objects contained a null." );
        if ( s.length() != 1 ) throw new IllegalStateException( "Input of list of String objects contained an element with other than one character." );
        if ( ! seen.add( s.codePointAt( 0 ) ) )
        {
            return Optional.of( s );
        }
    }
    return Optional.empty();
}

Usage.

List < String > inputX = List.of( "D" , "B" , "C" , "A" , "B" , "A" );
List < String > inputY = List.of( "D" , "B" , "C" , "A" , "E" , "T" );

System.out.println( App5.firstRecurringCharacter( inputX ).orElse( "No recurring characters." ) );
System.out.println( App5.firstRecurringCharacter( inputY ).orElse( "No recurring characters." ) );

When run.

B

No recurring characters.

String rather than list of characters

Of course in the code above you need not use code point integers given an input of strings with a single character each. You could just make a Set< String > rather than Set< Integer > for code points.

Where the code points are useful is in tearing apart a string of multiple characters. So the calling programmer need not pass a collection of single-character strings. Instead, a String of several characters could be passed.

public static Optional < String > firstRecurringCharacter ( String input )
{
    Objects.requireNonNull( input );
    int[] codePoints = input.codePoints().toArray();
    Set < Integer > seen = new HashSet <>();
    for ( int codePoint : codePoints )
    {
        if ( ! seen.add( codePoint ) )
        {
            return Optional.of( Character.toString( codePoint ) );
        }
    }
    return Optional.empty();
}

Usage.

String inputX = "DBCABA";
String inputY = "DBCAET";
String inputZ = "😷ABC😷ABC";

System.out.println( App5.firstRecurringCharacter( inputX ).orElse( "No recurring characters." ) );
System.out.println( App5.firstRecurringCharacter( inputY ).orElse( "No recurring characters." ) );
System.out.println( App5.firstRecurringCharacter( inputZ ).orElse( "No recurring characters." ) );

When run.

B

No recurring characters.

😷

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.