Konwertuj wartość logiczną na int w Javie

350

Jaki jest najbardziej akceptowany sposób konwersji booleanna intjęzyk Java?

hpique
źródło
8
Co całkowitymi można by pomyśleć odzwierciedlał truei falseodpowiednio?
Thorbjørn Ravn Andersen
4
Niektóre języki mają domyślną konwersję z int na boolean. Java nie. Jednak oficjalna implementacja zawiera pakiety SQL i uważam, że konwertują one „false” na 0.
hpique
4
@Peter Lawrey Nie, jeśli chcesz współpracować z innymi systemami, które nie mają wartości logicznych jako nieliczbowych typów danych.
hpique
6
@Peter Lawrey Pytanie tak naprawdę nie dotyczy mapowania wartości. Chodzi o to, jak wykonać konwersję w najbardziej przejrzysty, akceptowany sposób.
hpique
7
Technicznie kompilator Java już definiuje mapowanie. Prawda i fałsz są kompilowane odpowiednio do 1 i 0.
Antimony

Odpowiedzi:

583
int myInt = myBoolean ? 1 : 0;

^^

PS: prawda = 1 i fałsz = 0

Jonatha ANTOINE
źródło
59
W przypadku, gdy myBoolean oznacza wyrażenie logiczne, użycie nawiasu jest bardziej czytelne.
rsp
40
Tak jak w (foo && (!bar || baz)) ? 1 : 0. Oczywiście, jeśli jest to tylko identyfikator, pareny nie są konieczne ani pożądane.
Blrfl,
niezła sztuczka z boolean! Szukałem, może istnieje jakiś casting, taki jak (int) true = 1, ale
zauważam
1
dla początkujących takich jak ja (boolean expression) ? 1 : 0;byłoby bardziej zrozumiałe. Myślę, że myprzedrostek wyglądał jak zmienna.
dixhom
12
@Blrfl w przykładowych nawiasach jest koniecznością , a nie kwestią czytelności. foo && (!bar || baz) ? 1 : 0byłby błąd składniowy. (Wiem, że minęło 6 lat)
Konrad Morawski
150
int val = b? 1 : 0;
Grodriguez
źródło
idealna odpowiedź!
gaurav
59

Korzystanie z operatora trójskładnikowego jest najprostszym, najbardziej wydajnym i najbardziej czytelnym sposobem na robienie tego, co chcesz. Zachęcam do skorzystania z tego rozwiązania.

Nie mogę się jednak oprzeć zaproponowaniu alternatywnego, przemyślanego, nieefektywnego i nieczytelnego rozwiązania.

int boolToInt(Boolean b) {
    return b.compareTo(false);
}

Hej, ludzie lubią głosować na takie fajne odpowiedzi!

Edytować

Nawiasem mówiąc, często widziałem konwersje z wartości logicznej na int wyłącznie w celu porównania dwóch wartości (ogólnie w implementacjach compareTometody). Boolean#compareTojest właściwą drogą w tych konkretnych przypadkach.

Edytuj 2

Java 7 wprowadziła nową funkcję narzędzia, która działa bezpośrednio z typami pierwotnymi Boolean#compare(Dzięki shmosel )

int boolToInt(boolean b) {
    return Boolean.compare(b, false);
}
Barjak
źródło
1
Zostaną wprowadzone przez nowoczesne JIT, więc niekoniecznie nieefektywne. Dokumentuje również, dlaczego używany jest b.compareTo, aby był czytelny.
Thorbjørn Ravn Andersen
2
Może to być powolne, ponieważ musimy zawrzeć pierwotną wartość w obiekcie. Metoda operatora trójskładnikowego działa bezpośrednio z wartościami pierwotnymi bez konwersji, więc myślę, że jest bardziej wydajna.
barjak
5
1. Możesz używać Boolean.compare()i unikać autoboxowania. 2. Dokumentacja dla Boolean.compareTo()nie mówi, że zwróci 1, a jedynie „wartość dodatnią, jeśli ten obiekt reprezentuje prawda, a argument reprezentuje fałsz”.
shmosel
1
Właśnie wykonałem test konwertujący 1 000 000 losowych wartości logicznych i ta metoda była konsekwentnie szybsza niż ta oparta na operatorze trójskładnikowym. Ogolił się około 10ms.
Mapsy
3
@AlexT. jeśli robisz mikrobenchmark, powinieneś użyć ram, aby upewnić się, że mierzysz poprawnie. Zobacz openjdk.java.net/projects/code-tools/jmh .
Thorbjørn Ravn Andersen
48
boolean b = ....; 
int i = -("false".indexOf("" + b));
Thorbjørn Ravn Andersen
źródło
14
Myślę, że lepiej by to pasowało jako komentarz, a nie odpowiedź.
hpique
164
5 - b.toString().length
kennytm
5
@ ThorbjørnRavnAndersen Tak. Używanie jednej z innych, bardziej wydajnych, opublikowanych metod, które nie wymagają tego narzutu. Chyba że możesz wyjaśnić, w jaki sposób tworzenie obiektów ciągów w celu sprawdzenia wartości logicznej jest w jakikolwiek sposób wydajne.
b1nary.atr0phy
10
@ ThorbjørnRavnAndersen Nie mam kontroli nad tym, jak używane są moje metody i jak często są one wywoływane, co jest całkowicie kwestią. Poświęcasz zarówno wydajność, jak i czytelność, co absolutnie nie przynosi wymiernych korzyści.
b1nary.atr0phy
6
Jest to zdecydowanie kreatywne, ale nie mogę wymyślić żadnej korzyści z zastosowania tej metody. Jest bardziej szczegółowy i (wydaje mi się) mniej wydajny, ale z pewnością jest interesującą metodą.
Mike Baxter
27
public int boolToInt(boolean b) {
    return b ? 1 : 0;
}

prosty

Adam
źródło
24
import org.apache.commons.lang3.BooleanUtils;
boolean x = true;   
int y= BooleanUtils.toInteger(x);
Darkeniel
źródło
FWIW BooleanUtils.toIntegerjest zaimplementowany jako sprawiedliwy return bool ? 1 : 0;.
Solomon Ucko
Apache Commons może być przydatne, ale jest to po prostu śmieszne.
Eric Duminil
14

To zależy od sytuacji. Często najprostsze podejście jest najlepsze, ponieważ jest łatwe do zrozumienia:

if (something) {
    otherThing = 1;
} else {
    otherThing = 0;
}

lub

int otherThing = something ? 1 : 0;

Ale czasami warto użyć Enum zamiast flagi boolowskiej. Wyobraźmy sobie, że istnieją procesy synchroniczne i asynchroniczne:

Process process = Process.SYNCHRONOUS;
System.out.println(process.getCode());

W Javie wyliczanie może mieć dodatkowe atrybuty i metody:

public enum Process {

    SYNCHRONOUS (0),
    ASYNCHRONOUS (1);

    private int code;
    private Process (int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }
}
Hendrik Brummermann
źródło
6
Dodatkowym powodem korzystania z if zamiast ?:jest to, że możesz wstawić punkty przerwania wewnątrz bloków if.
Thorbjørn Ravn Andersen
12

Jeśli używasz Apache Commons Lang (który, jak sądzę, używa go wiele projektów), możesz po prostu użyć go w następujący sposób:

int myInt = BooleanUtils.toInteger(boolean_expression); 

toIntegermetoda zwraca 1, jeśli boolean_expressionjest prawdą, 0 w przeciwnym razie

triForce420
źródło
FWIW BooleanUtils.toIntegerjest zaimplementowany jako sprawiedliwy return bool ? 1 : 0;.
Solomon Ucko
8

Jeśli true -> 1i false -> 0mapowanie jest tym, czego chcesz, możesz:

boolean b = true;
int i = b ? 1 : 0; // assigns 1 to i.
kodaddict
źródło
6

Jeśli chcesz zaciemnić, użyj tego:

System.out.println( 1 & Boolean.hashCode( true ) >> 1 );  // 1
System.out.println( 1 & Boolean.hashCode( false ) >> 1 ); // 0
Christian Ullenboom
źródło
3

Pozwala zagrać z trikiem Boolean.compare(boolean, boolean). Domyślne zachowanie funkcji: jeśli obie wartości są równe, w 0przeciwnym razie zwraca -1.

public int valueOf(Boolean flag) {
   return Boolean.compare(flag, Boolean.TRUE) + 1;
}

Objaśnienie : Jak wiemy, domyślnym zwróceniem Boolean.compare jest -1 w przypadku niepoprawnego dopasowania, więc +1 ustaw wartość zwracaną na 0 dla Falsei 1 dlaTrue

Mumair
źródło
3
Boolean.compare(myBoolean, false)lepiej pasowałoby do cytowanego opisu
Vadzim
@Vadzim Tak rzeczywiście wygeneruje 1 i 0, porównując z fałszem, aw obecnym scenariuszu wygeneruje 0 i -1. Oba rozwiązania są w porządku, a +1 za komentarz :-)
mumair
0

Fakt, że muszę napisać metodę otoki wokół instrukcji if do rzutowania wartości, dodaje do i tak już ogromnej listy powodów, dla których java powinna po prostu umrzeć. I widząc, że operator trójskładnikowy nie jest nawet zawinięty w funkcję, ale po prostu kopiuje wklejony wszędzie, widzę boolowską obsadę po prostu doprowadza mnie do szału. Jest to strata cykli procesora i zniewaga dla czytelności kodu.

Również większość odpowiedzi tutaj ma setki pozytywnych opinii z zerowym wyjaśnieniem, co sprawia, że ​​zgaduję, że zła praktyka jest tylko wynikiem tak częstego narażenia na java. Gdybym napisał trójskładnikowego operatora do przesyłania wartości logicznej na int w jakimkolwiek współczesnym języku, zostałbym zwolniony następnego dnia z jakiejkolwiek pracy, jaką miałem. Więc dzisiaj zrezygnowałem z prób wykorzystania rozumu przy moich zadaniach java i postanowiłem przyjąć głupotę:

public static int booltoint(boolean nonsense) {
                                // Let's start with indenting using spaces, 16 of them to be precise
                                String[] ____int = new String[500];
                                ____int[0] = Boolean.toString(nonsense);
                                try {
                                                Thread.sleep(100); 
                                } catch (Exception e) {    }
                                Random rand = new Random();
                                int n = rand.nextInt((int)1e9);
                                int result = 0;
                                int other_Result = 1;
                                for (int i = -5; i < 2; i++) {
                                                try {
                                                                if (n == 35467247) return 5; // let's just fail with one in a billion chance
                                                                if ((5 - ____int[i].length()) == 1) {
                                                                                return ++result;
                                                                } else if(____int[i] == "false") {
                                                                                return --other_Result;
                                                                }
                                                } catch (Exception e) {
                                                                // This method will throw an exception 5 times every single time I 
                                                                // cast a boolean to int before returning an integer
                                                }
                                }
                                return (int)1e35;}
MuhsinFatih
źródło
-1
public static int convBool(boolean b)
{
int convBool = 0;
if(b) convBool = 1;
return convBool;
}

Następnie użyj:

convBool(aBool);
Regis_AG
źródło