I might suggest some names on which you can read further using Google.
1) cannonic Hoffman coding - no need to store a tree
But only the length of the symbols.
2) arithmetic encoding - A more interesting scenario is adaptive arithmetic coding that adapts the encoding to the probabilities of the words at encoding time.
3) front prefix coding - if words in your string have common prefixes like a dictionary for example, you might cut the prefix of a word and just store its length
And on decoding get the prefix from the previous word
Or a word in a certain index of the string that came before.
These are really easy to implement(also in java) and their pseudo code as well as elreal java implementations may be found in the first links of a Google search.
Of course there are many more techniques and the right ones depend on the actual use.
If you expand your question and give a use case , others and I may be able to fine tune the technique to the scenario.