简体   繁体   中英

Converting Int value to List of Integer digits

I have got an easy task to draw three int values. Then build a new int value from the highest digits from drawn values. Is there an easy way to convert an Int to List of Integers? I want to resolve this by streams but I need a List of Integers created from drawn value to find maxValue digit.

For example: 123, 256, 189 = 369

I have done this in a naive way, I'm still learning and start wondering if is an easier and more code efficient way.

public static List<Integer> convertingValue(int value) {
    List<Integer> intList = new ArrayList<>();
    char[] arr = String.valueOf(value).toCharArray();
    for (int i = 0; i < arr.length; i++) {
        intList.add(Character.getNumericValue(arr[i]));
    }
    return intList;
}

public static void main(String[] args) {
    IntSupplier is = () -> new Random().nextInt(999 - 100 + 1) + 100;
    List<Integer> figuresList =
            List.of(is.getAsInt(), is.getAsInt(), is.getAsInt());

    var list = figuresList
            .stream()
            .map(Basic02::convertingValue)
            .map(x -> x.stream().mapToInt(v -> v)
                    .max().orElseThrow(NoSuchElementException::new))
            .collect(Collectors.toList());

    System.out.println(list);
}
  1. It would be better to use Random::ints(streamSize, origin, bound) to create a stream of random numbers
  2. Convert each number into string, then use String::chars to get stream of characters for each number and find maximal digit for each number
  3. To get better representation of the result it is worth to build a String instead of the List<Integer> using custom collector on the basis of StringBuilder . Then this string may be converted then into int/Integer if needed.
String num = new Random().ints(3, 100, 1000)
    .peek(System.out::println) // debug print
    .mapToObj(Integer::toString)
    .map(s -> s.chars().map(Character::getNumericValue).max().getAsInt())
    .collect(Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString));
System.out.println("---\n" + num);

Output:

893
677
436
---
976

Existing code may also be refactored to return immediately the maximal digit instead of the list of integers:

public static int getMaxDigit(int value) {
    return String.valueOf(value)
        .chars() // IntStream
        .map(Character::getNumericValue)
        .max() // OptionalInt
        .getAsInt(); // int
}

Then List<Integer> may be collected as:

var list = new Random().ints(3, 100, 1000) // IntStream
    .map(MyClass::getMaxDigit)
    .boxed()
    .collect(Collectors.toList());

Or String may be collected in another way:

var str = new Random().ints(3, 100, 1000) // IntStream
    .map(MyClass::getMaxDigit)
    .mapToObj(Integer::toString)
    .collect(Collectors.joining());

Here is one approach that uses divison / and the remainder
operator % to break down the numbers into their digits.

  • first, create an array of 3 values between 100 and 999 inclusive
  • the stream each array and find the maximum digit of each value:
    • first, iterate each value divided by 10 .
      eg 248 -> 248, 24, 2
    • then get each digit by using the remainder operator.
      eg 248 % 10 = 8, 24 % 10 = 4, 2 % 10 = 2
  • now find the maximum of those three digits.
  • and reduce them by converting back to a three digit number.
for (int i = 0; i < 10; i++) {
    int[] values = r.ints(3, 100, 1000).toArray();
    int result = Arrays.stream(values)
            .map(vv -> IntStream
                    .iterate(vv, k -> k > 0, k -> k / 10)
                    .map(a -> a % 10).max().getAsInt())
            .reduce(0, (a, b) -> a * 10 + b);
    
    System.out.println(
            Arrays.toString(values) + " --> " + result);
}

Prints something like the following.

[772, 840, 915] --> 789
[981, 118, 981] --> 989
[924, 415, 507] --> 957
[293, 827, 740] --> 987
[476, 479, 858] --> 798
[414, 555, 163] --> 456
[737, 898, 855] --> 798
[496, 989, 526] --> 996
[369, 944, 279] --> 999
[148, 317, 115] --> 875

Using streams, you can convert numbers to strings, then split these strings into the arrays of digits, then take the maximum digits from the arrays and concatenate them back into a single string, and then finally parse an integer from that string:

public static void main(String[] args) {
    System.out.println(maxDigits(123, 256, 189)); //369
}
public static int maxDigits(int... numbers) {
    String max = Arrays.stream(numbers)
            // IntStream to Stream<String>
            .mapToObj(String::valueOf)
            // split each string into an array
            // of digits and take the maximum
            .map(str -> Arrays.stream(str.split(""))
                    .max(Comparator.naturalOrder())
                    .orElse(""))
            // join max digits into one string
            .collect(Collectors.joining());
    // return integer value
    return Integer.parseInt(max);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM