There's a book called Effective Java too.
There are different categories of data binding in Java. The most advanced are the Object models, like JDO, JPA, etc. They basically use a map to move data from objects to tables, and you never touch database directly as it is all handled transparently. Another is the typical "object binds to a row" technique, of which JDO is a good example. Finally, there is handling the database directly, which you use JDBC. Use the tool most appropriate to your code logic.
In general, you'll find that with Java it's not a "one solution only" environment. Some of the problems have been solved multiple times in different ways to achieve different results.
It sounds like "Managed Extensibility Framework" is a subtle copy of the J2EE server concept. J2EE has undergone at least three major revisions over the past decade. If you want to use J2EE, remember that it provides services to items within wrappers called "containers". This means you will have to adapt your code to meet the container service agreements. There is a bit of up-front learning involved, but once you understand the environment it isn't hard. You also don't need to use the entire J2EE environment and you can embed your own solutions to those provided by the J2EE server. It's a pick and choose type arrangement, precious little is forced on you.
J2EE also describes a lot of corporate technologies that may live independently of a J2EE server, so if you don't like the J2EE environment (for whatever reason) you can always include the JAR files and use the libraries without the J2EE server.
Some people have decided that the initial J2EE servers were too restrictive, so you have an almost-J2EE server called Spring. The J2EE web containers arrived pretty early on the scene in Java, so you can get "web container only" servers, like Tomcat or Jetty.
With Java, there is probably even more documentation about the garbage collector, but you have to deal with it's behaviour less. Java's garbage collector is generally much better behaved, and it doesn't have to deal with pointer support which partially makes .net's garbage collector something you do need to tend to from time to time.
That said, dereference anything you want collected. If the logic stores items in a HashMap as a cache, consider using SoftReferences, which will not be considered as references in garbage collection. Java doesn't reference count, so don't worry about circular references, you can dereference a cycle of references and they will all be collected.
The algorithm the GC uses changes depending on memory availability. In low memory utilization situations, it will copy live objects to a new page and free the old page (so compaction is obtained nearly for free. In higher memory situations, it uses a mark, sweep, and compact cycle typical of other garbage collectors. It also stages it's memory in three generational segments to order object by the frequency they should be checked for usage in the current running program.
All of that said, the real kicker is that Android uses the Java language, but it doesn't run a JVM. It runs an "I-can't-believe-it's-not-Java!" JVM-work alike that makes significant changes to the class loader and class file format. That means that you need to learn how the Davlik Virtual Machine operates and differs from the JVM.
Have fun! There is a lot more choice in Java land that you're probably accustomed to; however, many of the most popular Java tools have been ported to .net land, so you won't find the entire landscape foreign.