Regarding functional programming in Java, the most important design rule is to avoid mutability. We use it only in places, where it makes sense and we use it internally, only, i.e. mutability does not leak to the outside as public API. Within the last years I deduced these three simple rules to achieve it:
i. Don't try to create purely functional programs with Java. Simply spoken, Java is not the right language for that.
ii. It is most important to follow these rules consistently and make no exceptions other than stated.