#Sorting a list on three properties

1 messages · Page 1 of 1 (latest)

terse ridge
#

I am using a comparator to sort a list based on three properties. I want entries to be at the end of the list if any of the following conditions are true

isNullable == true
required == false
defaultValue != null

This stub works in most cases, but I was informed of an edge case were we get error Comparison method violates its general contract! How can I fix it?

    public static Comparator<CodegenProperty> propertyComparatorByNotNullableRequiredNoDefault = new Comparator<CodegenProperty>() {
        @Override
        public int compare(CodegenProperty one, CodegenProperty another) {
            if (one.isNullable == another.isNullable && one.required == another.required && (one.defaultValue == null) == (another.defaultValue == null))
                return 0;
            else if (!one.isNullable && one.required && one.defaultValue == null)
                return -1;
            else
                return 1;
        }
    };
gilded hingeBOT
#

<@&987246399047479336> please have a look, thanks.

exotic nacelle
#

what about:

Comparator.comparing(property -> property.isNullable) // might need custom keyComparator
    .thenComparing(property -> property.required) // might need custom keyComparator
    .thenComparing(property -> property.defaultValue, Comparator.nullsLast(...));
#

something like this

#

but I am not sure how the default boolean keyComparator works

#

let me do some testing so I can tell for sure

terse ridge
#

Thanks a lot. I just tried this, and it works, but changes a bit more than I was hoping for.

    public static Comparator<CodegenProperty> propertyComparatorByNotNullableRequiredNoDefault = new Comparator<CodegenProperty>() {
        @Override
        public int compare(CodegenProperty one, CodegenProperty another) {
            if (one.isNullable == another.isNullable && one.required == another.required && (one.defaultValue == null) == (another.defaultValue == null))
                return 0;
            else if ((!one.isNullable && another.isNullable) || (one.required && !another.required) || (one.defaultValue == null && another.defaultValue != null))
                return -1;
            else
                return 1;
        }
    };
exotic nacelle
#

ok this should actually work:

Comparator.comparing(p -> p.isNullable)
    .thenComparing(p -> !p.required)
    .thenComparing(p -> p.defaultValue != null);
terse ridge
#

This works for the edge case and without changing much of what I already have.

    public static Comparator<CodegenProperty> propertyComparatorByNotNullableRequiredNoDefault = new Comparator<CodegenProperty>() {
        @Override
        public int compare(CodegenProperty one, CodegenProperty another) {
            if (one.isNullable == another.isNullable && one.required == another.required && (one.defaultValue == null) == (another.defaultValue == null))
                return 0;
            else if (!one.isNullable && one.required && one.defaultValue == null)
                return -1;
            else
                return one.name.compareTo(another.name);
        }
    };
exotic nacelle
#

but only if you want it in that order

terse ridge
#

Same as the original code but the else compares the name.

exotic nacelle
#

ok yea my solution does smth slightly different

terse ridge
#

Okay, thank you for your help!

#

I take it back, my change doesn't quite work. How do I get your version in here?

exotic nacelle
#

well my version wont work as expected lol

exotic nacelle
#

iirc

#

it only checks the second value if the first are equal

#

and you didnt state if thats what you want

#

so idk

terse ridge
#

I think it will work.

exotic nacelle
terse ridge
#

It's a huge class.

exotic nacelle
terse ridge
exotic nacelle
#

hm maybe it doesnt register the generics peepo_think

#

maybe try this:

#
Comparator.<CodegenProperty, Boolean>comparing(p -> p.isNullable)
    .thenComparing(p -> !p.required)
    .thenComparing(p -> p.defaultValue != null);
terse ridge
#

Okay, that runs. Let me study it to see if it is the right output.

exotic nacelle
#

I am wondering why it doesnt detect the generics automatically peepo_think

#

well I think you can even use this shorter version:

Comparator.comparing((CodegenProperty p) -> p.isNullable)
    .thenComparing(p -> !p.required)
    .thenComparing(p -> p.defaultValue != null);
exotic nacelle
terse ridge
#

Looks like this is what I want

   public static Comparator<CodegenProperty> propertyComparatorByNotNullableRequiredNoDefault =
            Comparator.comparing(p -> p.isNullable || !p.required || p.defaultValue != null);
exotic nacelle
#

I wouldnt be too sure

#

now if the first element is null and the second element got required = false, then they both evaluate to true and be equal

terse ridge
#

I think that is okay. If any of my three conditions stated above are true, then it should be at the end. Looks like that is what happens.

exotic nacelle
#

ah ok, if thats what you want

terse ridge
#

Yes, this is generating C# code. The constructor requires that parameters with a default value be at the end of the signature.

exotic nacelle
#

using java to generate c# code lol

#

thats interesting

terse ridge
#

It uses mustache templates to generate any language you like.