If the value of hashmap is a Boolean then is it worth using a Hashset ? My question would be confusing but its not easy to frame up right words to ask either. The code below explains my problem. The code solves the following question Given some cubes, can cubes be arranged such that an input word can be formed from top view of cubes? eg: assume an imaginary cube with only 3 surfaces where cube1: {a, b, c} and cube2 {m, n, o}, then word an can be formed but word ap cannot be formed. I have two approaches for this question, use a HashMap<String, boolean> or use a Hashset. Advantage of Hashmap is that it does not cause a lot of rehashing. advantage of hashset is code looks (atleast to me) as smaller and cleaner. What is the right solution / industry wide followed practice in such cases"

OPTION 1: char[][] m is the set of cubes where rows are cubes and columns are surfaces

public static boolean checkWord(char[][] m, String word) {
        final Map<Character, Boolean> charAvailable = new HashMap<Character, Boolean>();
        char[] chWords = word.toCharArray();

        for (char ch : chWords) {
            charAvailable.put(ch, true);
        }

        return findWordExists(m, charAvailable, 0);
    }

    private static boolean findWordExists (char[][] m, Map<Character, Boolean> charAvailable, int cubeNumber) {

        if (cubeNumber == m.length) {
            Collection<Boolean> booleanValues = charAvailable.values();
            for (boolean available : booleanValues) {
                if (available) return false;
            }
            return true;
        }

        for (int i = 0; i <  m[cubeNumber].length; i++) {
            if (charAvailable.get(m[cubeNumber][i]) == Boolean.TRUE) {
                charAvailable.put(m[cubeNumber][i], false);
                if (findWordExists(m, charAvailable, cubeNumber + 1)) {
                    return true;
                }
                charAvailable.put(m[cubeNumber][i], true);
            }

        }
        return false;
    }

OPTION 2: char[][] m is the set of cubes where rows are cubes and columns are surfaces

public static boolean checkWord(char[][] m, String word) {
        final Set<Character> charAvailable = new HashSet<Character>();
        char[] chWords = word.toCharArray();

        for (char ch : chWords) {

            System.out.println(" adding: " + ch);
            charAvailable.add(ch);
        }
        return findWordExists(m, charAvailable, 0);
    }

    private static boolean findWordExists (char[][] m, Set<Character> charAvailable, int cubeNumber) {
        if (cubeNumber == m.length) {
            return charAvailable.isEmpty();
        }

        for (int i = 0; i <  m[cubeNumber].length; i++) {
            if (charAvailable.contains(m[cubeNumber][i])) {
                charAvailable.remove(m[cubeNumber][i]);
                if (findWordExists(m, charAvailable, cubeNumber + 1)) {
                    return true;
                }
                charAvailable.add(m[cubeNumber][i]);
            }
        }
        return false;
    }
有帮助吗?

解决方案

The HashSet will be more memory-efficient and time-efficient, but leaves some ambiguity depending on the application.

Consider the scenario where a program processes many custom objects of some type User, and records their answer to a "yes or no" question. There are 3 possible states a User could be in during this processing:

  1. User says "yes"
  2. User says "no"
  3. User has not been processed yet

Using a HashSet alone (i.e. without an additional data structure), depending on the situation it may be ambiguous as to whether or not a User not found in the HashSet has replied "no", or simply not been processed yet. A HashMap, although being less efficient because it must store multiple Boolean instances, would allow you to differentiate between the 3 cases listed above.

Note that in practicality, there are many cases where the 3rd case can be eliminated (e.g. by iterating through every User instance so you can assume each processed User is only encountered once), and the HashSet would be the appropriate choice.

其他提示

The solution that uses Set will probably be more readable, and easier to maintain - for example you avoid a whole class of problems when you modify your code like "what happens if I put a false value in the map - will it break my code?".

As a side note, Java's HashSet is quite inefficient memory-wise and actually uses a HashMap under the covers. Still, in most cases it is code readability and maintainability that matters most and not implementation details like this.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top