2
votes

Java - amusant de convertir une chaîne (4 caractères) en int et inversement

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);


1 commentaires

Probablement plus propre pour faire value.getBytes (StandardCharsets.US_ASCII) et convertir en int en utilisant un ByteBuffer ou quelque chose.


6 Réponses :


2
votes

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)
}


4 commentaires

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.



3
votes

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.


0 commentaires

1
votes

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());


2 commentaires

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



3
votes

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".


3 commentaires

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.



1
votes

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());


2 commentaires

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.



1
votes
  • Création d'une chaîne de valeurs de décalage pour parcourir la somme.
  • Masquez chaque caractère.
  • Convertir en chaîne.
  • Et rejoignez un collectionneur.
  •    String str = IntStream.of(0, 8, 16, 24)
                .mapToObj(i->(char)(sum>>i&0xff)+"")
                 .collect(Collectors.joining());
    

1 commentaires

Je ne savais pas qu'il était possible d'avoir une chaîne ajoutant un caractère à une chaîne vide