Mi colega y yo tuvimos un error que se debió a nuestra suposición de que allMatch()
regresaría una llamada de flujo vacía false
.
if (myItems.allMatch(i -> i.isValid()) {
//do something
}
Por supuesto, es culpa nuestra por asumir y no leer la documentación. Pero lo que no entiendo es por qué allMatch()
regresa el comportamiento predeterminado para una secuencia vacía true
. ¿Cuál fue el motivo de esto? Al igual que el anyMatch()
(que al contrario devuelve falso), esta operación se usa de manera imperativa que sale de la mónada y probablemente se usa en una if
declaración. Teniendo en cuenta estos hechos, ¿hay alguna razón por la que tener la allMatch()
opción predeterminada true
en un flujo vacío sea deseable para la mayoría de los usos?
allMatch
devuelve verdadero, también debería hacerloanyMatch
. Además, para el caso vacío,allMatch(...) == noneMatch(...)
que también es extraño.i -> i.isValid()
, puede escribirFoo::isValid
(dóndeFoo
está la clase que está transmitiendo, por supuesto)Respuestas:
Esto se conoce como verdad vacía . Todos los miembros de una colección vacía satisfacen su condición; después de todo, ¿puedes señalar uno que no lo haga?
Del mismo modo,
anyMatch
devuelvefalse
, porque no puede encontrar un elemento de su colección que coincida con la condición. Esto es confuso para mucha gente, pero resulta ser la forma más útil y consistente de definir "cualquiera" y "todos" para conjuntos vacíos.fuente
1
mientras que la suma de un conjunto vacío de números es0
. Son los elementos neutrales para la multiplicación / suma. En el caso de booleanos usted tiene queTrue and x = x
yFalse or x = x
por lo tanto, si se generalizaand
yor
a secuencias (que es loall
yany
son) se termina conTrue
yFalse
para el caso vacío, es decir, los respectivos elementos neutros.anyMatch
pruebas de ausencia de positivos,allMatch
pruebas de ausencia de negativos.Aquí hay otra forma de pensar en esto:
allMatch()
Es para&&
lo quesum()
es a+
Considere las siguientes declaraciones lógicas:
IntStream.of(1, 2).sum() + 3 == IntStream.of(1, 2, 3).sum() IntStream.of(1).sum() + 2 == IntStream.of(1, 2).sum()
Esto tiene sentido porque
sum()
es solo una generalización de+
. Sin embargo, ¿qué sucede cuando eliminas un elemento más?IntStream.of().sum() + 1 == IntStream.of(1).sum()
Podemos ver que tiene sentido definir
IntStream.of().sum()
, o la suma de una secuencia vacía de números, de una manera particular. Esto nos da el "elemento de identidad" de la suma, o el valor que, cuando se agrega a algo, no tiene efecto (0
).Podemos aplicar la misma lógica al
Boolean
álgebra.Stream.of(true, true).allMatch(it -> it) == Stream.of(true).allMatch(it -> it) && true
Más genéricamente:
Si
stream = Stream.of()
entonces esta regla aún debe aplicarse. Podemos usar el "elemento de identidad" de && para resolver esto.true && thing == thing
, entoncesStream.of().allMatch(it -> it) == true
.fuente
Cuando llamo
list.allMatch
(o sus análogos en otros idiomas), quiero detectar si algún elementolist
no coincide con el predicado. Si no hay elementos, es posible que ninguno no coincida. Mi siguiente lógica elegiría elementos y esperaría que coincidieran con el predicado. Para una lista vacía, no elegiré ningún elemento y la lógica seguirá siendo sólida.¿Qué pasa si se
allMatch
devuelvefalse
por una lista vacía?Mi lógica sencilla fallaría:
if (!myList.allMatch(predicate)) { throw new InvalidDataException("Some of the items failed to match!"); } for (Item item : myList) { ... }
Necesitaré recordar reemplazar el cheque por
!myList.empty() && !myList.allMatch()
.En resumen,
allMatch
regresartrue
por una lista vacía no solo es lógicamente sólido, sino que también se encuentra en el camino feliz de la ejecución, que requiere menos verificaciones.fuente
if (!allMatch)
Parece que la base es la inducción matemática. Para la informática, una aplicación de esto podría ser un caso base de un algoritmo recursivo.
La clave aquí es que está "vacuosamente satisfecho", lo que, por naturaleza, es algo engañoso. Wikipedia tiene una discusión decente al respecto.
fuente
Si bien esta pregunta ya se ha respondido correctamente multiplicado por veces, quiero introducir un enfoque más matemático.
Para eso quiero considerar la corriente como un Conjunto (en el sentido matemático). Entonces
corresponde a while
corresponde a .
Que la segunda parte sea falsa es bastante obvio ya que no hay elementos en el conjunto vacío. El primero es un poco más complicado. Puede aceptar que sea cierto por definición o buscar en las otras respuestas algunas de las razones por las que debería ser así.
Un ejemplo para ilustrar esta diferencia son proposiciones como "Todos los humanos que viven en Marte tienen 3 patas" (verdadero) y "Hay un ser humano viviendo en Marte con 3 patas" (falso).
fuente