0

I'm new to programming in java. The below source code is found in a book, when i try to execute the program it is showing some incorrect data.

public class Pair<T> {

    private T first;
    private T second;

    public Pair() {
        first = null;
        second = null;
    }

    public Pair(T first, T second) {
        this.first = first;
        this.second = second;
    }

    public T getFirst() {
        return first;
    }

    public T getSecond() {
        return second;
    }

    public void setFirst(T newValue) {
        first = newValue;
    }

    public void setSecond(T newValue) {
        second = newValue;
    }  
}

Logic to find the min and max value of the string array

public class ArrayAlg {

    public static Pair<String> minmax(String[] arr) {
        if (arr == null || arr.length == 0)
            return null;

        String min = arr[0];
        String max = arr[0];

        for (int i = 1; i < arr.length; i++) {
            if (min.compareTo(arr[i]) > 0)
                min = arr[i];
            if (max.compareTo(arr[i]) < 0)
                max = arr[i];
        }
        return new Pair<String>(min, max);

    }
}

public static void main(String[] args) {

        String[] words = { "Mary", "had", "a", "little", "lamb" };
        Pair<String> obj = ArrayAlg.minmax(words);
        System.out.println("Minvalue " + obj.getFirst());
        System.out.println("Maxvalue " + obj.getSecond());

    }

If you execute the above program, it displays Minvalue = Mary and MaxValue = little. The value a in the String array is the Minimum Value but in this case it is showing Mary as the Min Value.
Can anyone tell me the better approach to find the Minimum and Maximum value in the String array?

explv
  • 2,709
  • 10
  • 17
Aishu
  • 1,310
  • 6
  • 28
  • 52

4 Answers4

3

The output you got is the correct output, since the natural ordering of Strings is lexicographical order, in which upper case letters come before lower case letters. Hence Mary is the "smallest" String.

In order not to use the natural ordering, don't use String's compareTo method. Instead you can implement whatever logic you see fit to determine which String is smaller. One way of introducing alternative ordering is passing a Comparator<String> instance to your minmax method and using its compare method to compare the Strings.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • Why not help by showing a readily available comparator for the purpose: `String.CASE_INSENSITIVE_ORDER`. Or `Collator.getInstance()`? – Andreas Jun 30 '16 at 10:36
  • @Andreas I'm not sure what the desired ordering was. It's possible that the only problem with the output was the case sensitive ordering, but I can't be sure of that. – Eran Jun 30 '16 at 10:37
  • Since there's very high probability that is exactly what OP needs, you should suggest it, rather than (or in addition to) only saying *"implement whatever logic you see fit"*, implying that OP would have to write the `Comparator` from scratch. That's not very useful. – Andreas Jun 30 '16 at 10:41
3

I think, for you purposes it's better to use String method compareToIgnoreCase().

But it depends on you understanding what does Minimum string and Maximum string is.

Also, there is preffered way to compare any objects - via Comparator.

public static Pair<String> minmax(String[] arr) {
    if (arr == null || arr.length == 0)
        return null;

    Arrays.sort(arr, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.compareToIgnoreCase(o2); // to compare by lexicographical order
            //return o1.length() - o2.lenth(); // to compare by length
        }
    });

    return new Pair<String>(arr[0], arr[arr.length - 1]);
}

Here are some links to follow:

Community
  • 1
  • 1
ar4ers
  • 740
  • 5
  • 19
  • can u please modify the code and update based on the question posted above – Aishu Jun 30 '16 at 10:27
  • I dunno how to modify, – Aishu Jun 30 '16 at 10:28
  • @Aishu, I modified as little to fit you code with minimum changes. – ar4ers Jun 30 '16 at 10:32
  • Why not use the freely available `String.CASE_INSENSITIVE_ORDER` comparator, rather than creating your own doing the same thing? Also, sorting the entire array has two problems: 1) It modifies the array, which may not be appropriate. 2) It's slower than just finding min/max. – Andreas Jun 30 '16 at 10:33
  • @ar4ers - May I know what is the output u r getting? – Aishu Jun 30 '16 at 10:38
  • String[] words = { "mary", "had", "a", "little", "lamb" }; - This is my string array – Aishu Jun 30 '16 at 10:39
  • As per ur logic the output is Minvalue = a Maxvalue = mary – Aishu Jun 30 '16 at 10:40
  • but Max Value should be little not marry – Aishu Jun 30 '16 at 10:40
  • @Aishu okay, I don't understand your sort logic. But I tried to show you the common method of solving this kind of problems. So you can do it by yourself :-) – ar4ers Jun 30 '16 at 10:49
  • @Aishu why `little` should be the `max`? In the lexicographical order `l` is above `m`. – ar4ers Jun 30 '16 at 11:29
  • yeah, as i already mentioned, this example is taken from the book, So i thought of asking an alternative from u guys – Aishu Jun 30 '16 at 11:36
  • the value "little" has the highest length in the string array, that's y – Aishu Jun 30 '16 at 11:38
  • @Aishu then just replace `o1.compareToIgnoreCase(o2)` with `o1.length() - o2.length()` – ar4ers Jun 30 '16 at 11:40
2

You will need to use a Comparator for this. You can sort the words alphabetically, ignoring case, by using the String.CASE_INSENSITIVE_ORDER Comparator.

In Java 8 this can be achieved easily using Lambdas:

public final Pair<String> miniMax(final String[] words) {
    final String min = Arrays.stream(words).min(String.CASE_INSENSITIVE_ORDER).orElse(null);
    final String max = Arrays.stream(words).max(String.CASE_INSENSITIVE_ORDER).orElse(null);
    return new Pair<>(min, max);
}

Testing:

String[] words = { "Mary", "had", "a", "little", "lamb" };
System.out.println(miniMax(words));

Output:

a, Mary
explv
  • 2,709
  • 10
  • 17
1

compareTo() compares the strings lexicographically, meaning that uppercase letters come before lowercase letters, since that is the order in Unicode. Instead, do one of the following:

Alternatively, for a good Java 8 implementation, see answer by arizzle.

So, your loop could be:

for (int i = 1; i < arr.length; i++) {
    if (min.compareToIgnoreCase(arr[i]) > 0)
        min = arr[i];
    if (max.compareToIgnoreCase(arr[i]) < 0)
        max = arr[i];
}

Or:

Comparator<String> comp = Collator.getInstance();
for (int i = 1; i < arr.length; i++) {
    if (comp.compare(min, arr[i]) > 0)
        min = arr[i];
    if (comp.compare(max, arr[i]) < 0)
        max = arr[i];
}
Community
  • 1
  • 1
Andreas
  • 154,647
  • 11
  • 152
  • 247