I can't speak authoritatively about Java, but it looks like map-reduce is available in Java 8 by casting a collection to a stream [0]. Considering the definitions of map and reduce can help one see how they can replace loops/counters:
MAP: Take a collection, say a list/array or a dictionary/hash, and perform some function on each member of the collection, returning a new collection who's members are the return values for each original member. It's a loop, but no loop!
REDUCE: Do the same thing as map, but carry along an output variable, and have your function's output for each member (potentially) mutate that output variable. Summing is a basic example.
I'm not specifically recommending preferring this in Java as a step towards functional programming. It's in, uh, more terse languages like Python and Ruby where the payoff is obvious [1][2]. And among not-functional programming languages, it's not just dynamic languages, either. Consider Dart (and seriously, consider Dart) [3]. Also, Javascript, which has had many features shoehorned-in over the years, has these and related functions.
One other other thing. Functional thinking has greatly changed the landscape of client-server applications that are hosted in the cloud as well. If your aim is apps, maybe don't bother to master the skills needed to set up and maintain a Linux server (although if you follow OP's other suggestions, you're well on your way). Instead, consider your backend as a network of microservices, functions, that each do one thing and do it with side effects only when necessary. The host for your app? Poof! That's AWS/GCP/Azure's problem.
One other thing. You will be thinking functions first if you get into data science, say with Python/Pandas. In general, Pandas functions are vectorized, meaning that they operate on members of a collection in parallel. You really don't want to write a loop that iterates over some 5,000,000 member collection and applies some expensive function serially.
MAP: Take a collection, say a list/array or a dictionary/hash, and perform some function on each member of the collection, returning a new collection who's members are the return values for each original member. It's a loop, but no loop!
REDUCE: Do the same thing as map, but carry along an output variable, and have your function's output for each member (potentially) mutate that output variable. Summing is a basic example.
I'm not specifically recommending preferring this in Java as a step towards functional programming. It's in, uh, more terse languages like Python and Ruby where the payoff is obvious [1][2]. And among not-functional programming languages, it's not just dynamic languages, either. Consider Dart (and seriously, consider Dart) [3]. Also, Javascript, which has had many features shoehorned-in over the years, has these and related functions.
[0] https://www.java67.com/2016/09/map-reduce-example-java8.html
[1] Double some numbers Python: result = map(lambda x: x + x, array_of_numbers)
[2] In Ruby: result = array_of_numbers.map{|x| x + x}
[3] In Dart: result = arrayOfNumbers.map((x) => x + x).toList();