Comparing Array Operations in Java and Ruby Programming Language.
Introduction
- I have been coding in Java all my career, but in my recent job, I am learning Ruby.
- While Ruby and Java both are Object-oriented languages, Ruby is a dynamically typed & Interpreted language while Java is mostly statically typed and compiled language.
- Considering my knowledge of both languages I am writing this article to list different operations on Array that we can perform on Array in Java vs Ruby.
- I have no intention to say X is better than Y coz this kind of comparison is always biased and provokes the developer community on the other side.
The programming language that puts food on table is the best programming language in the world. at least for you!
Creating Array
- Both the language does descent job in array creation. We can instantiate Array by new or we can create one without it.
Ruby Style
irb(main):018:0> arr = [ 1, 2, 3 ]
=> [1, 2, 3]
irb(main):019:0> arr = Array.new([1,2,3])
=> [1, 2, 3]
Java Style
jshell> int[] arr = { 1, 2, 3 };
o/p==> { 1, 2, 3 }
jshell> var arr = new int[]{1,2,3};
o/p ==> { 1, 2, 3 }
Initialize Array with Value
- Both languages provide enough capabilities to initialize an array with value. Ruby also allows us to pass blocks to initialize values dynamically which is kind of interesting compare to Java.
Ruby Style
irb(main):025:0> arr = Array.new
=> []
irb(main):026:0> arr = Array.new(3,0) # with val 0
=> [0, 0, 0]
irb(main):028:0> arr = Array.new(3) # with default val nil
=> [nil, nil, nil]
irb(main):027:0> arr = Array.new(3,"5") # with val as string
=> ["5", "5", "5"]
irb(main):029:0> arr = Array.new(3) { Hash.new } # with val as Empty hash
=> [{}, {}, {}]
irb(main):030:0> arr = Array.new(3) {|i| {i => i*2} } # with val passed as exp with block
=> [{0=>0}, {1=>2}, {2=>4}]
Java Style
jshell> var arr = new int[3];
arr ==> int[3] { 0, 0, 0 }
jshell> var arr = new String[3];
arr ==> String[3] { null, null, null}
jshell> Arrays.fill(arr, "5");
jshell> arr
arr ==> String[3] { "5", "5", "5" }
jshell> var arr = new HashMap[3];
arr ==> HashMap[3] { null, null, null }
jshell> Arrays.fill(arr, new HashMap());
jshell> arr
arr ==> HashMap[3] { {}, {}, {} }
jshell> var arr = new HashMap[3];
...> HashMap[] hashMaps = IntStream.range(0, arr.length)
...> .mapToObj(i -> {
...> HashMap<Integer, Integer> map = new HashMap<>();
...> map.put(i, i*2);
...> return map;
...> })
...> .toArray(HashMap[]::new);
hashMaps ==> HashMap[3] { {0=0}, {1=2}, {2=4} }
Iterate Array Elements
- Both the language has iterator to iterate over each element of the array.
In ruby we can use each to iterate over each element and map to convert the array to any modified version we want. - Similarly In Java we have Stream API that support these features.
Ruby Style
# iterate over each element and print it
irb(main):016:0> [1, 2, 3, 4].each { |n| p n*2 }
2
4
6
8
# map element to desired value
irb(main):018:0> [1, 2, 3, 4].map { |n| n*2 }
=> [2, 4, 6, 8]
# Ruby provides a method on Array to iterate over elements with an index.
irb(main):017:0> [1,2,3].each_with_index.map { |n, i| "#{n}:#{i}"}
o/p => ["1:0", "2:1", "3:2"]
Java Style
jshell> Arrays.stream(new int[]{ 1, 2, 3, 4}).forEach(System.out::println)
1
2
3
4
- I couldn’t find a method in stream API to get the index along with the element, but we can make use IntStream to provide a range as an index to operate on.
jshell> IntStream
.range(0, arr.length)
.mapToObj(i -> arr[i]+":"+i)
.toArray(String[]::new);
o/p => { "1:0", "2:1", "3:2" }
Filter Element in Array
- Both Ruby and Java does good job in allowing us to filter the element in array.
- Ruby has specific method for filtering out the element with we dont need with “reject” and “select” for the element that we need.
- While Java has filter operator on Streams , which we can pass predicate to filter on positive or negative condition.
Ruby Style
# filtering elements that are even
irb(main):019:0> [1, 2, 3, 4].select { |i| i%2==0 }
=> [2, 4]
irb(main):020:0> [1, 2, 3, 4].reject { |i| i%2==0 }
=> [1, 3]
Java Style
jshell> Arrays.stream(new Integer[]{ 1, 2, 3, 4})
.filter(n -> n%2==0)
.toArray(Integer[]::new)
$6 ==> Integer[2] { 2, 4 }
jshell> Arrays.stream(new Integer[]{ 1, 2, 3, 4})
.filter(Predicate.not(n -> n%2==0))
.toArray(Integer[]::new)
$9 ==> Integer[2] { 1, 3 }
Merge multiple Arrays
- In Ruby we can merge array as easily as summing up two array with “+”.
There is also concat method to add array in Ruby - In Java its not so easy to just add the array, but certainly not immpossible. We have one option to do using streams api that can concat streams and then we can convert them to Array.
- We can also convert array to arraylist which is more prefer data structure in Java than array . ( Arraylist is essentially dynamic array in Java) and then add arraylist with Collection.addAll method.
Ruby Style
irb(main):031:0> [1,2,3,4] + [5,6,7,8]
=> [1, 2, 3, 4, 5, 6, 7, 8]
irb(main):036:0> [1,2,3,4].concat [5,6,7,8]
=> [1, 2, 3, 4, 5, 6, 7, 8]
# * operator expands/splat the array and push each element to the left side array
irb(main):037:0> [1,2,3,4].push(*[5,6,7,8])
=> [1, 2, 3, 4, 5, 6, 7, 8]
Java Style
jshell> Stream
.concat(Arrays.stream(x), Arrays.stream(y))
.toArray(Integer[]::new)
$24 ==> Integer[9] { 4, 2, 3, 6, 1, 2, 4, 5, 6 }
jshell> var x = new Integer[]{ 4, 2, 3, 6 }
x ==> Integer[4] { 4, 2, 3, 6 }
jshell> var y = new Integer[]{ 1, 2,4,5,6}
y ==> Integer[5] { 1, 2, 4, 5, 6 }
jshell> Stream.of(x,y).flatMap(Stream::of).toArray(Integer[]::new)
$27 ==> Integer[9] { 4, 2, 3, 6, 1, 2, 4, 5, 6 }
Sorting Array
- Both Java and Ruby provide good coverage on sorting the element in Array.
Ruby Style
# sort the array in ascending order
irb(main):022:0> [4,2,3,6].sort
=> [2, 3, 4, 6]
# compare each pair of element and sort them
irb(main):023:0> [4,2,3,6].sort { |x,y| y <=> x}
=> [6, 4, 3, 2]
# first sort then reverse them for descending order
irb(main):026:0> [4,2,3,6].sort.reverse
=> [6, 4, 3, 2]
Java Style
// sort the array in ascending order
jshell> Arrays.stream(new Integer[]{4,2,3,6}).sorted().toArray(Integer[]::new)
$12 ==> Integer[4] { 2, 3, 4, 6 }
// sort the array in descending order
jshell> Arrays
.stream(new Integer[]{4,2,3,6})
.sorted(Comparator.reverseOrder())
.toArray(Integer[]::new)
$13 ==> Integer[4] { 6, 4, 3, 2 }
// convert array to list and then sort them using Collections sort.
jshell> var list = Arrays.asList(x)
list ==> [4, 2, 3, 6]
jshell> Collections.sort(list, (a,b) -> a - b)
jshell> list
list ==> [2, 3, 4, 6]
Conclusion
- In this article, we covered various array operations that we can perform using Ruby or Java programming language.
- Both languages provide a good set of features with less code to write to operate on top of an array.
- I don’t find verbosity in Java since we used streams API.