Dla mnie najważniejsze aspekty to:
a) niemutowalność, która to jest defaultowa w językach funkcyjnych.
W javie też możesz używać typówów niemutowalnych, ale kompilator Ci w tym nie pomaga. Np. nie wie, że nigdzie nie podstawiasza wyniku (bo zakłada, że może robisz jakisside effekt).
Np. java nie ostrzeże Cie, jak zrobisz bigDecimal.add(otherDecimal) i nie podstawisz do wyniku.
b) wyrażenia, zamiast zdań.
if, while, switch itp. są w jezykach funkcyjnych wyrażeniami czyli nie da się zapomnieć, że coś trzeba zrobić w else.
c) bogatszy type system. Pozwala wprowadzic więcej abstrakcji (fold, monady itp),
Dzięki temu już w typie widać np. jakie są efekty uboczne i jakie ograniczenia.
Bogactwo na szybko:-)
https://stackoverflow.com/questions/26440436/how-does-scalas-type-system-compare-to-javas
Dodatkowo fp języki w wiekszości są bardzo type friendly. Czyli wprowadzanie dodatkowych typów jest tanie i nie boli. Pomocne są wszelkiego rodzaju type aliasy, konwersje itp.
Np. w javie raczej zapiszesz class Person { int age; }, a w funkcyjnym prędzej class Person { Age age;} (bo mniej boli). Przy czym poczatkowo Age to może być alias na unsigned int, który potem np. będzie dostawał dodatkowe ograniczenia.
TLDR: programować dość funkcyjnie można też w javie. To robię, to też pomaga, ale mam dużo więcej boiler plate, musze borykać się z toną i tak nie fuknkcyjnego kodu (biblioteki), a do tego kompilator mi nie pomaga.