As others said, given the constraints of using arrays and primitives, your code looks good, efficient while requiring two passes. If you can choose to use objects and collections, your code could be rewritten to be shorter and simpler.
Java collections framework
An array
in Java is purposely quite limited in its features. The primary reason for array
is to make easier porting of code from other languages such as C. An array can also be useful when (a) working with primitives and (b) compact use of memory is a priority — not the case generally in business-oriented apps.
For day-to-day work within Java, we use the feature-rich Java collections framework bundled with Java or a similar framework from a 3rd-party such as Google Guava.
In Java, the common alternative to array
is ArrayList
class. This class masks the use of arrays underneath, to give the illusion of an array that is growing or shrinking as needed. For small sized lists, you can simply rely on this auto-sizing.
The collections framework only handles objects, not primitives. But Java will use its auto-boxing feature to automatically promote your int
primitive values into Integer
objects. Objects take more memory and are a tiny bit slower, but have much more flexible.
Java has a for-each feature to loop an array or collection, to simplify the syntax of a for
loop.
Notice how “not less than minimum” is another way of saying “is greater than or equal to minimum”. Same effect, use either as a matter of style.
ArrayList< Integer > numbers = new ArrayList<>() ;
for( int i : data ) { // for-each syntax, to loop an array.
if ( !( i < min ) && ( i < max ) ) { // Half-Open `[)`, beginning/lower is inclusive while the ending/higher is exclusive.
numbers.add( i ) ; // Auto-boxing converts your `int` primitive to an `Integer` object.
} // Else discard this number, and move on to the next.
}
Just one loop needed. Much shorter code, easier to read.
You likely will want to return the result as the more general List
rather than ArrayList
. This is polymorphism in action, if you’ve studied that OOP concept.
public static List< Integer > filterOutTooLowAndTooHigh( int[] ints , int min , int max )
{
ArrayList< Integer > numbers = new ArrayList<>() ;
for( int i : ints ) {
if ( !( i < min ) && ( i < max ) ) {
numbers.add( i ) ;
}
}
return numbers ;
}
You might want to sort the returned numbers. The Collections
class (notice the plural s
) has utility methods for sorting.
Collections.sort( numbers ) ;
ArrayList
actually grows by allocating a new array and copying over from the old array. So the new array may be sized larger than you actually need. So when you have finished adding elements to the ArrayList
, you may want to trim the underlying array to the minimum size needed.
Collections.trimToSize( numbers ) ;
Lastly, if you have very large arrays, you may want to set the initial size of the ArrayList
. This avoids the growing process of allocating a new array and copying over, lather, rinse, repeat. Again do not worry about this for arrays in the dozens, hundreds, or few thousand size unless your app does this work many times.
int initialCapacity = 100_000 ;
ArrayList< Integer > numbers = new ArrayList<>( initialCapacity ) ;
Put this all together.
public static List< Integer > filterOutTooLowAndTooHigh( int[] ints , int min , int max )
{
int initialCapacity = 100_000 ;
ArrayList< Integer > numbers = new ArrayList<>( initialCapacity ) ;
for( int i : ints ) {
if ( !( i < min ) && ( i < max ) ) { // Half-Open `[)`, beginning/lower is inclusive while the ending/higher is exclusive.
numbers.add( i ) ;
}
}
Collections.sort( numbers ) ;
Collections.trimToSize() ;
return numbers ;
}
I have not tested that code, but should get you going in the right direction.
You likely could do this in even less code by using Java Streams. But as a beginner, you should not use streams until later. First get comfortable with working with arrays and collections manually as discussed here.
By the way, this might help you: Resize an Array while keeping current elements in Java?