0

I'm just barely learning Java and need to accomplish something in Java 8, but I'm struggling to figure out the most efficient way to do it (coming from a PHP background). Essentially I'm trying to give it a regular array, run some calculations, and then save some of those values in a new array where the original key is preserved.

So basically the original array is something like:

0 => 3
1 => 5
2 => 6
3 => 8

and the new array will be an associative array where the keys are specifically assigned like:

1 => 5
3 => 8

In order to help myself visualize it in something I'm more familiar with, I've gotten everything I need working in PHP, and it looks something like this:

$array = array( 8, 3, 2, 9, 1, 15 );

$new_array = array();

foreach ( $array as $key => $value ) {

    // Calculate something and build new array, for example...
    if ( 5 > $value ) {

        $new_value = $value + 5;

        $new_array[ $key ] = $new_value;
    }
}

So in this example, $new_array would be:

1 => 8
2 => 7
4 => 6

I would swear I've seen something where I can do just a basic for loop and access key and value but I can't find where I read that, and everything else I'm finding now talks about iterating through "hash maps" using forEach(), so that seems like the standard approach, but when I try array.forEach((k, v) -> // Calculations.... it tells me that it "cannot find symbol" for array in that context, which is being set immediately prior as int[] array = { // numbers }. As I'm understanding it, I have to convert the array to a hash map in order to be able to use a key/value pair in the foreach, but apparently I'm doing something wrong there as well...

So I guess here are my questions...

  1. Can I use a basic for loop for this or I need to convert the array to a hash map in order to access the key/value pairs? How? I don't need to use any specific method, just looking for the most efficient.
  2. I have import java.util.Arrays; for other reasons - do I need to import something else?

Thanks for your help.

UPDATE -------------------------

To clarify, I'll need to do something similar later in the code again using $new_array as the source, so I need to be able to get the keys and not just the iteration count.

So for example if I were to wrap the foreach in a while loop, where the first time it starts with $array and each subsequent time it sets $array as $new_array to run the calculations again.

So in other words, I can't rely on the iteration count to match the keys.

6
  • Use a basic for loop and store the result in a Map using the index variable as the key. Commented Nov 28, 2020 at 12:29
  • @JoakimDanielson Later in the code I'll need to do something similar with the $new_array though, so the counter won't match the keys. Is there a way to specifically get the key value? Commented Nov 28, 2020 at 12:32
  • Not sure what you mean but notice that the variable you call $new_array is a Map in java. It should probably work the same in java as in php Commented Nov 28, 2020 at 12:35
  • Sorry - I'll add an update to the question and see if I can explain. Commented Nov 28, 2020 at 12:37
  • I still don’t understand, you will have the keys if you use a Map. And if you want to use a for each loop instead then why not manually keep track of the index with a variable. Or use a Map instead of an array to start with Commented Nov 28, 2020 at 12:44

2 Answers 2

2

It is possible to use Stream API to convert array into map in a functional way:

  • use IntStream.range to create a stream of integers
  • collected into map using Collectors.toMap:

For a new map, filter operation can be applied to select values less than 5.

// these imports to be added
import java.util.*;
import java.util.stream.*;

int [] array = {8, 3, 2, 9, 1, 15};
Map<Integer, Integer> map = IntStream.range(0, array.length) // stream of int indexes
                                     .boxed() // stream of Integer
                                     .collect(Collectors.toMap(
                                         i -> i,        // use index as key
                                         i -> array[i]  // get array element as value
                                     ));

Map<Integer, Integer> mapNew = IntStream.range(0, array.length)
                                        .boxed()
                                        .filter(i -> array[i] < 5)
                                        .collect(Collectors.toMap(i -> i, i -> array[i] + 5));

System.out.println("old map:" + map);
// printing each entry in new map using lambda
mapNew.forEach((k, v) -> System.out.println(k + " -> " + v));

// use common for loop by entries
System.out.println("----");
for(Map.Entry<Integer, Integer> entry : mapNew.entrySet()) {
    System.out.println(entry.getKey() + " => " + entry.getValue());
}

Output:

old map:{0=8, 1=3, 2=2, 3=9, 4=1, 5=15}
1 -> 8
2 -> 7
4 -> 6
----
1 => 8
2 => 7
4 => 6
Sign up to request clarification or add additional context in comments.

6 Comments

Trying this out - I'm getting a 'cannot find symbol' on Map. Do I need to import something?
yes, sure, I updated the answer. These imports needed: import java.util.*; to get Map and import java.util.stream.*; to get IntStream, Collectors
This may be a different question but is there a way to set up the foreach not as a lambda so I can use local variables inside it (that were set outside of it)?
Sure, foreach loop for map iterate over map.entrySet()
Amazing, thanks! Last question - the array is small but if it gets quite large - say 10,000 - do you know if there would be any performance issues from calling something like getKey() or it that pretty fast?
|
1

You can use a regular for loop:

int [] array = {8, 3, 2, 9, 1, 15};
Map<Integer, Integer> map = new HashMap<>();

// Print the results
for (int i = 0; i < array.length; i++) {
    if (5 > array[i]) {
        map.put(i, array[i] + 5);
    }
}
        
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + "=>" + entry.getValue());
}

6 Comments

Thanks! Sorry I updated my question - I have to get the actual keys as they may not match the iteration count. Is there a way to modify this to do that?
@Shoelaced If there are keys then it is not an array. The source data is in a map?
The initial $array is just a regular array, but it sounds like $new_array output will be a map, and since I'll need to run the same foreach again on $new_array, it sounds like I need to first convert $array to a map and go from there?
Yes, I guess that is what you need to do. Arrays and maps are (obviously) very different and are accessed using different semantics so the same loop won't work on both.
I see... how would I convert the array to a map? I can search around but if you can update your answer that'd be helpful too.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.