S'il vous plaît ne demandez pas pourquoi mais je dois stocker une chaîne (max 4 caractères) dans une valeur entière (donc 4 octets).
J'ai d'abord écrit ceci et cela fonctionne:
StringBuffer out = new StringBuffer(); while (sum > 0) { int ch = sum & 0xff; sum >>= 8; out.append((char) ch); }
Je n'ai pas pu penser à une solution fonctionnelle pour le chemin du retour.
String value = "AAA"; int sum = IntStream.range(0, value.length()) .limit(4) .map(i -> value.charAt(i) << (i * 8)) .sum(); System.out.println(sum);
6 Réponses :
c'est essentiellement un char [4] qui est transféré vers un int puis vers l'arrière. En réalité, j'imagine que cela fonctionnerait
public static String getStr(int encoded){ return ((char)(encoded >> 24) + ((char)((encoded >> 16) 0xFF) + ((char)((encoded >> 8) & 0xFF) + ((char)((encoded) & 0xFF) }
Mais ce n'est pas une manière fonctionnelle
Hé bien oui. mais la question était de savoir comment faire de manière fonctionnelle c'est-à-dire streams, lambda, etc ... pas avec une fonction java :)
@freedev Qu'est-ce qui n'est pas fonctionnel? Semble suivre tous les paradigmes. Sauf si vous le souhaitez sous la forme d'un lambda, auquel cas il est assez facile de le convertir en un seul.
@MatthewKerian Au moins, vous avez eu des commentaires sur les raisons pour lesquelles ils n'aimaient pas votre réponse.
Une solution pourrait être:
StringBuilder out = IntStream.iterate(sum, s -> s > 0, s -> s >> 8) .mapToObj(s -> (char) (s & 0xff)) .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append); System.out.println(out.toString());
Remarque: j'ai utilisé un IntStream.iterate
une> surcharge disponible à partir de Java 9.
C'est assez similaire au vôtre, mais cela vous sera peut-être utile
String str = IntStream.iterate(sum, s -> s > 0, s -> s >> 8) .mapToObj(s -> String.valueOf((char)(s & 0xff))) .collect(Collectors.joining());
Inutile d'utiliser >> =
. Personne ne lit les s
après le quart de travail.
@Michel_T. cette solution semble être la plus courte, mais nous avons toujours besoin de java 9 pour que cela fonctionne
Ce n'est peut-être pas la meilleure façon de le reconvertir en String
en utilisant des flux; votre boucle while
existante semble plus propre et peut être plus performante. Cependant, il existe une solution de flux.
String result = IntStream.range(0, 4) .map(i -> (value >>> 24 - (i * 8)) & 0xFF) .dropWhile(i -> i == 0) .mapToObj(v -> String.valueOf( (char) v)) .collect(Collectors.joining());
Cela génère des indices d'octet, prend la valeur d'octet spécifique, la mappe à un char
, les joint à un Chaîne
. Il supprime également les valeurs 0 de début à l'aide de Méthode Java 9+ dropWhile
.
J'ai corrigé cela pour obtenir le bon ordre en ajoutant le "24 -" pour saisir l'octet le plus significatif en premier.
Avec une valeur
de 0x10101 * 65
, cela renvoie "AAA"
. Avec une valeur
de 0x10101 * 65 + 1
, cela renvoie "AAB"
.
Je ne pense pas que vous ayez besoin du "24 -" car le & 0xFF
devrait supprimer les octets non significatifs, essayez ceci: final String str1 = IntStream.range (0, 4) .map (i -> (valeur >> (i * 8)) & 0xFF) .filter (v -> v> 0) .mapToObj (v -> String.valueOf ((char) v)) .collect (Collectors.joining ( )) ;;
Quand j'ai essayé "AAB" j'ai obtenu "BAA" et j'ai dû inverser les octets avec le "24 -".
très probablement vous avez eu un autre problème, vérifiez la solution que j'ai publiée dans le commentaire.
Merci à tous pour votre contribution. J'ai trouvé une autre solution à partager avec vous:
String str = IntStream.iterate(sum, s -> s >> 8) .limit(4) .filter(s -> s > 0) .mapToObj(s -> String.valueOf((char) (s & 0xff))) .collect(Collectors.joining());
Je suis vraiment confus. Cela semble être une façon horrible de le faire, pourquoi voudriez-vous le faire de cette façon?
@MatthewKerian J'ai déjà essayé d'expliquer pourquoi. Vous n’avez jamais entendu parler de programmation fonctionnelle? C'est tout. La boucle while que j'ai écrite dans la question est très probablement la solution la meilleure et la plus simple, mais elle n'a pas les avantages du paradigme fonctionnel. La question est de savoir comment s'amuser avec la programmation fonctionnelle.
String str = IntStream.of(0, 8, 16, 24) .mapToObj(i->(char)(sum>>i&0xff)+"") .collect(Collectors.joining());
Je ne savais pas qu'il était possible d'avoir une chaîne ajoutant un caractère à une chaîne vide
Probablement plus propre pour faire
value.getBytes (StandardCharsets.US_ASCII)
et convertir en int en utilisant un ByteBuffer ou quelque chose.