I want to calculate the amount of different prime factors of every integer up to n. For example, 12 = 2 * 2 * 3, so it has 2 different prime factors, 2 and 3. I want to store each of these values in an array result[], of size n+1, in which result[i] contains the number of different prime factors of the integer i.
I have to use the following external method in my solution:
List<Integer> getPrimes(int n) {
// create array to determine which numbers are prime
boolean isPrime[] = new boolean[n+1];
for(int i=2; i<=n; i++)
isPrime[i] = true; // assume all are prime, we'll filter below
for(int i=3; i*i<=n; i+=2) {
if (isPrime[i]) { // i is prime, so...
for(int j=i*i; j<=n; j+=i) // remove all its multiples
isPrime[j] = false; // by updating array
}
}
// create list with only the prime numbers
List<Integer> primes = new LinkedList<>();
primes.add(2);
for(int i=3; i<=n; i+=2)
if (isPrime[i])
primes.add(i);
return primes;
}
which uses the Sieve of Eratosthenes to return a List of all prime numbers up to n. This was my solution:
int[] getNumPrimeFactors(int n) {
int[] result = new int[n + 1];
int counter; // counts the number of different prime factors
boolean isPrime = true;
List<Integer> primeList = getPrimes(n);
for (int i = 2; i < result.length; i++) {
counter = 0;
// checks if i is prime
if (i % 2 == 0) {
isPrime = false;
} else {
for (int j = 3; j * j <= i; j += 2) {
if (i % j == 0)
isPrime = false;
}
}
// if i isnt prime, counts how many different prime factors it has
if (!isPrime) {
for (int prime : primeList) {
if (i % prime == 0)
counter++;
}
result[i] = counter;
} else {
result[i] = 1;
}
}
return result;
}
This algorithm produces the correct results, however, I want to be able to test for n <= 5_000_000, and it isn't efficient enough. Is there any way I can improve the code for very large instances of n? Here are some example test results: 
Thank you very much for your help :)