Echar un vistazo a Andreas_D delrespuesta para la explicación.En el código anterior todos los valores nulos y +Infinito de valores se controlan de tal manera que ellos pasar a la final.
Actualización 1:
Como jarnbjo y aioobe señala un fallo en la implementación.Así que he pensado que es mejor para restringir la implantación de Número.
Tenga en cuenta que se producirá un error si el doble de los valores están demasiado lejos. Me gustaría convertir al Doble de los valores y de la llamada compareTo en ellos, o de uso mayor que/menor que la de los operadores. null se va a lanzar la excepción de todos modos.¿tienes una mejor idea de manejarlo ? Puso una condición no es así, todos los null va a ir en la final. Aquí es lo que yo pienso : en el compare método, comprobar si o1 y o2 son instanceof de Comparable. Si sí, entonces el código de Java ya ha implementado la mejor comparación posible para los tipos numéricos de uso que (llamando o1.compareTo(o2). Si no se implementa Comparable, yo recomendaría que trabajan fuera de la BigDecimal en lugar de Double. Buena pregunta +1, pero una mala respuesta, -1. Utilizar la solución que aioobe siempre – funciona, esto no!
Como jarnbjo señala en su respuesta, no hay manera de implementar un Comparator<Number> correctamente, como instancias de Number puede muy bien representar números mayores que Double.MAX_VALUE (y que, desafortunadamente, tan lejos como el Number interfaz nos permite “ver”). Un ejemplo de un Number más grande que Double.MAX_VALUE es
Instancias de {Double, Float}.NEGATIVE_INFINITY y {Double, Float}.POSITIVE_INFINITY
Tenga en cuenta que estos siempre deben venir antes de/después de cualquier BigDecimal aunque el BigDecimal.doubleValue puede devolver Double.NEGATIVE_INFINITY o Double.POSITIVE_INFINITY
null elementos
Una mezcla de todo lo anterior, y
Desconocido implementaciones de Number que también implementa Comparable.
(Esto parece ser una suposición razonable ya que todos Numbers en la norma API implementa Comparable.)
@SuppressWarnings("unchecked")classNumberComparatorimplementsComparator<Number>{//Special values that are treated as larger than any other.privatefinalstaticList<?> special =Arrays.asList(Double.NaN,Float.NaN,null);privatefinalstaticList<?> largest =Arrays.asList(Double.POSITIVE_INFINITY,Float.POSITIVE_INFINITY);privatefinalstaticList<?> smallest =Arrays.asList(Double.NEGATIVE_INFINITY,Float.NEGATIVE_INFINITY);publicint compare(Number n1,Number n2){//Handle special cases (including null)if(special.contains(n1))return1;if(special.contains(n2))return-1;if(largest.contains(n1)|| smallest.contains(n2))return1;if(largest.contains(n2)|| smallest.contains(n1))return-1;//Promote known values (Byte, Integer, Long, Float, Double and//BigInteger) to BigDecimal, as this is the most generic known type.BigDecimal bd1 = asBigDecimal(n1);BigDecimal bd2 = asBigDecimal(n2);if(bd1 !=null&& bd2 !=null)return bd1.compareTo(bd2);//Handle arbitrary Number-comparisons if o1 and o2 are of same class//and implements Comparable.if(n1 instanceofComparable<?>&& n2 instanceofComparable<?>)try{return((Comparable) n1).compareTo((Comparable) n2);}catch(ClassCastException cce){}//If the longValue()s differ between the two numbers, trust these.int longCmp =((Long) n1.longValue()).compareTo(n2.longValue());if(longCmp !=0)return longCmp;//Pray to god that the doubleValue()s differ between the two numbers.int doubleCmp =((Double) n1.doubleValue()).compareTo(n2.doubleValue());if(doubleCmp !=0)return longCmp;//Die a painful death...thrownewUnsupportedOperationException("Cannot compare "+ n1 +" with "+ n2);}//Convert known Numbers to BigDecimal, and the argument n otherwise.privateBigDecimal asBigDecimal(Number n){if(n instanceofByte)returnnewBigDecimal((Byte) n);if(n instanceofInteger)returnnewBigDecimal((Integer) n);if(n instanceofShort)returnnewBigDecimal((Short) n);if(n instanceofLong)returnnewBigDecimal((Long) n);if(n instanceofFloat)returnnewBigDecimal((Float) n);if(n instanceofDouble)returnnewBigDecimal((Double) n);if(n instanceofBigInteger)returnnewBigDecimal((BigInteger) n);if(n instanceofBigDecimal)return(BigDecimal) n;returnnull;}}
Aquí es un pequeño programa de prueba (aquí es un ideone.com demo):
publicclassMain{publicstaticvoid main(String[] args){List<Number> li =newArrayList<Number>();//Add an Integer, a Double, a Float, a Short, a Byte and a Long.
li.add(20); li.add((short)17);
li.add(12.2); li.add((byte)100);
li.add(0.2f); li.add(19518926L);
li.add(Double.NaN); li.add(Double.NEGATIVE_INFINITY);
li.add(Float.NaN); li.add(Double.POSITIVE_INFINITY);//A custom Number
li.add(newBoolNumber(1));
li.add(newBoolNumber(0));//Add two BigDecimal that are larger than Double.MAX_VALUE.BigDecimal largeDec =newBigDecimal(""+Double.MAX_VALUE);
li.add(largeDec/*.multiply(BigDecimal.TEN)*/);
li.add(largeDec.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN));//Add two BigInteger that are larger than Double.MAX_VALUE.BigInteger largeInt = largeDec.toBigInteger().add(BigInteger.ONE);
li.add(largeInt.multiply(BigInteger.TEN));
li.add(largeInt.multiply(BigInteger.TEN).multiply(BigInteger.TEN));//...and just for fun...
li.add(null);Collections.shuffle(li);Collections.sort(li,newNumberComparator());for(Number num : li)System.out.println(num);}staticclassBoolNumberextendsNumber{boolean b;publicBoolNumber(int i){ b = i !=0;}publicdouble doubleValue(){return b ?1d:0d;}publicfloat floatValue(){return b ?1f:0f;}publicint intValue(){return b ?1:0;}publiclong longValue(){return b ?1L:0L;}publicString toString(){return b ?"1":"0";}}}
Su aplicación es buena, pero creo que es mejor para restringir los tipos en tiempo de ejecución,ya que cualquier nueva aplicación de Número puede ser efectuado y el manejo de todos los casos en la misma comparador de no ser práctico.Además, no podemos obtener números superiores al doble del número de casos.Comprobar mi respuesta actualizada. Bien, usted pidió una manera de ordenar Number s, no de una manera de ordenar una mezcla de Integer, Double, Float, Short, Byte, a la derecha? Me dicen que no puede ser resuelto por completo, pero usted puede conseguir lejos. Usted dice, “Además, no podemos obtener números superiores al doble del número de casos.” Depende de si te refieres a la claseNumber. (Seguro que podemos conseguir Numbers más del doble de Numbers.) aioobe:Sí su derecho .Le he preguntado así,pero entonces yo no era consciente de que BigInteger y BigDecimals también implementado Número.De cualquier manera gracias por tu respuesta. Ahora que ya sabes 🙂 y ahora usted sabe qué tan lejos se puede llegar cuando se trata de la clasificación de Numbers. Tanto nuestras soluciones puede producir un error en tiempo de ejecución cuando se alimenta con extraños Numbers, pero mi solución va a llegar un poco más que la tuya. aioobe: Su aplicación no necesita muy extraño Números de error. Anhela tener un una precisión mucho mayor que el doble de grandes valores, por lo que el uso de doubleValue() como una reserva se producirá a comparar por ejemplo, de Largo.MAX_VALUE y (de Largo.MAX_VALUE-1), ya que son equivalentes después de ser arrojado a doble.
Usted necesitará una solución para null valores, porque puede estar en la colección – usted no puede crear una colección de objetos que no toma null.
Así que usted puede comprobar para null y tirar IllegalArgumentException – con el efecto secundario, que usted no será capaz de ordenar “contaminado” listas y tienen que manejar las excepciones en tiempo de ejecución.
Otra idea es convertir un null a algún tipo de número. He mostrado que este enfoque (basada en la propia solución de su propia respuesta) por la conversión de cualquier null a Double.NaN por la convención. También podría considerar la conversión de ellos a 0 o a Double.POSITIVE_INFINITY o Double.NEGATIVE_INFINITY si desea null valores ordenados a los extremos.
Collections.sort(li,newComparator<Number>(){@Overridepublicint compare(Number o1,Number o2){//null values converted to NaN by conventionDouble d1=(o1 ==null)?Double.NaN: o1.doubleValue();Double d2=(o2 ==null)?Double.NaN: o2.doubleValue();return d1.compareTo(d2);}});
Más Información
Aquí un poco de código que muestra cómo los valores especiales son manejados por “default”:
Set<Double> doubles =newTreeSet<Double>();
doubles.add(0.);//doubles.add(null); //uncommenting will lead to an exception!
doubles.add(Double.NaN);
doubles.add(Double.POSITIVE_INFINITY);
doubles.add(Double.NEGATIVE_INFINITY);for(Double d:doubles)System.out.println(d);
El resultado (sin null addded) es:
-Infinity0.0InfinityNaN
+1,yo tiene su punto. Tenga en cuenta que esta aplicación puede ver new BigDecimal("" + Double.MAX_VALUE).multiply(BigDecimal.TEN) mayor que Double.POSITIVE_INFINITY.
Respuesta Simple: no Se puede. Una propiedad de un Número de aplicación puede tener una mayor precisión o un mayor rango de valor de lo que está disponible a través de la getXXX() los métodos definidos para el valor real en el Número de la interfaz.
Puede dar un código de ejemplo para ilustrar esto ? No sin escribir una gran cantidad de evidente código. ¿Qué ocurre si dos el Número de casos con los valores internos “Doble.MAX_VALUE * 2” y “Doble.MAX_VALUE * 3”. Su getDouble() la aplicación debe truncar el valor de ajuste en el rango de un doble y por lo tanto, probablemente ambos devuelven el Doble.MAX_VALUE, lo que hace imposible aplicar un genérico comparador de estos tipos. hablando Número de instancia de BigDecimal o BigInteger ? Son sólo ejemplos. Cualquiera puede escribir sus propias implementaciones de el Número de la interfaz, usted no tiene que restringir su consideración a las clases en la API estándar. yo entiendo.Así es, hay alguna forma de restringir el acceso a cierto número de implementaciones de uso de medicamentos genéricos ?
Echar un vistazo a Andreas_D del respuesta para la explicación.En el código anterior todos los valores nulos y +Infinito de valores se controlan de tal manera que ellos pasar a la final.
Actualización 1:
Como jarnbjo y aioobe señala un fallo en la implementación.Así que he pensado que es mejor para restringir la implantación de Número.
Actualización 2:
Utilizando la guayaba es limitada lista (no permitir la entrada de nulo o no admitido tipo de lista):
null se va a lanzar la excepción de todos modos.¿tienes una mejor idea de manejarlo ?
Puso una condición no es así, todos los
null
va a ir en la final.Aquí es lo que yo pienso : en el
compare
método, comprobar si o1 y o2 soninstanceof
deComparable
. Si sí, entonces el código de Java ya ha implementado la mejor comparación posible para los tipos numéricos de uso que (llamandoo1.compareTo(o2)
. Si no se implementaComparable
, yo recomendaría que trabajan fuera de laBigDecimal
en lugar deDouble
.Buena pregunta +1, pero una mala respuesta, -1. Utilizar la solución que aioobe siempre – funciona, esto no!
OriginalEl autor Emil
Como jarnbjo señala en su respuesta, no hay manera de implementar un
Comparator<Number>
correctamente, como instancias deNumber
puede muy bien representar números mayores queDouble.MAX_VALUE
(y que, desafortunadamente, tan lejos como elNumber
interfaz nos permite “ver”). Un ejemplo de unNumber
más grande queDouble.MAX_VALUE
esLa solución a continuación, sin embargo, maneja
Byte
s,Short
s,Integer
s,Long
s,Float
s yDouble
sArbitraria gran
BigInteger
sArbitraria gran
BigDecimal
sInstancias de
{Double, Float}.NEGATIVE_INFINITY
y{Double, Float}.POSITIVE_INFINITY
Tenga en cuenta que estos siempre deben venir antes de/después de cualquier
BigDecimal
aunque elBigDecimal.doubleValue
puede devolverDouble.NEGATIVE_INFINITY
oDouble.POSITIVE_INFINITY
null
elementosUna mezcla de todo lo anterior, y
Desconocido implementaciones de
Number
que también implementaComparable
.(Esto parece ser una suposición razonable ya que todos
Number
s en la norma API implementa Comparable.)Aquí es un pequeño programa de prueba (aquí es un ideone.com demo):
…que imprime (he quitado un par de ceros):
Bien, usted pidió una manera de ordenar
Number
s, no de una manera de ordenar una mezcla deInteger
,Double
,Float
,Short
,Byte
, a la derecha? Me dicen que no puede ser resuelto por completo, pero usted puede conseguir lejos. Usted dice, “Además, no podemos obtener números superiores al doble del número de casos.” Depende de si te refieres a la claseNumber
. (Seguro que podemos conseguirNumbers
más del doble deNumbers
.)aioobe:Sí su derecho .Le he preguntado así,pero entonces yo no era consciente de que BigInteger y BigDecimals también implementado Número.De cualquier manera gracias por tu respuesta.
Ahora que ya sabes 🙂 y ahora usted sabe qué tan lejos se puede llegar cuando se trata de la clasificación de
Numbers
. Tanto nuestras soluciones puede producir un error en tiempo de ejecución cuando se alimenta con extrañosNumbers
, pero mi solución va a llegar un poco más que la tuya.aioobe: Su aplicación no necesita muy extraño Números de error. Anhela tener un una precisión mucho mayor que el doble de grandes valores, por lo que el uso de doubleValue() como una reserva se producirá a comparar por ejemplo, de Largo.MAX_VALUE y (de Largo.MAX_VALUE-1), ya que son equivalentes después de ser arrojado a doble.
OriginalEl autor aioobe
Usted necesitará una solución para
null
valores, porque puede estar en la colección – usted no puede crear una colección de objetos que no tomanull
.Así que usted puede comprobar para
null
y tirarIllegalArgumentException
– con el efecto secundario, que usted no será capaz de ordenar “contaminado” listas y tienen que manejar las excepciones en tiempo de ejecución.Otra idea es convertir un
null
a algún tipo de número. He mostrado que este enfoque (basada en la propia solución de su propia respuesta) por la conversión de cualquiernull
aDouble.NaN
por la convención. También podría considerar la conversión de ellos a0
o aDouble.POSITIVE_INFINITY
oDouble.NEGATIVE_INFINITY
si deseanull
valores ordenados a los extremos.Más Información
Aquí un poco de código que muestra cómo los valores especiales son manejados por “default”:
El resultado (sin
null
addded) es:Tenga en cuenta que esta aplicación puede ver
new BigDecimal("" + Double.MAX_VALUE).multiply(BigDecimal.TEN)
mayor queDouble.POSITIVE_INFINITY
.OriginalEl autor Andreas_D
Respuesta Simple: no Se puede. Una propiedad de un Número de aplicación puede tener una mayor precisión o un mayor rango de valor de lo que está disponible a través de la getXXX() los métodos definidos para el valor real en el Número de la interfaz.
No sin escribir una gran cantidad de evidente código. ¿Qué ocurre si dos el Número de casos con los valores internos “Doble.MAX_VALUE * 2” y “Doble.MAX_VALUE * 3”. Su getDouble() la aplicación debe truncar el valor de ajuste en el rango de un doble y por lo tanto, probablemente ambos devuelven el Doble.MAX_VALUE, lo que hace imposible aplicar un genérico comparador de estos tipos.
hablando Número de instancia de BigDecimal o BigInteger ?
Son sólo ejemplos. Cualquiera puede escribir sus propias implementaciones de el Número de la interfaz, usted no tiene que restringir su consideración a las clases en la API estándar.
yo entiendo.Así es, hay alguna forma de restringir el acceso a cierto número de implementaciones de uso de medicamentos genéricos ?
OriginalEl autor jarnbjo
probar mi java algoritmo de ordenación:
OriginalEl autor Nathan Nelson