Mastering Java Fundamentals: From Source Code to Efficient HashMap and Concurrency Practices
The article shares a seasoned Java developer’s journey from superficial framework use to deep source‑code study, emphasizing solid fundamentals such as HashMap internals, concurrency mechanisms, and performance‑oriented coding practices to build a robust J2EE skill set.
Many newcomers ask basic J2EE questions, prompting the author to stress that Java beginners must first solidify their fundamentals and define what mastering those fundamentals actually means.
After more than ten years of J2EE development, the author reflects on early years when Java felt easy because only business logic was written, yet a lingering sense of inadequacy persisted, causing frustration and doubt about personal competitiveness.
During that period the author chased every new framework and API, learning them superficially without a deep understanding, which left a feeling of insecurity despite the effort.
Eventually the author decided to change direction by reading the JDK source code—starting with core data structures and multithreading—focusing on the implementation details rather than just using APIs. This disciplined study lasted several months and led to rapid, meaningful growth.
As the saying goes, "Talk is cheap, show me the code." The author illustrates this with a simple HashMap example: Map<Integer, String> map = new HashMap<>(); Understanding the HashMap source reveals that it is backed by an array of buckets (later transformed into linked lists or trees for large buckets), follows a space‑for‑time trade‑off, and uses a constructor with initial capacity and load factor to control performance.
Key performance factors include a fast, well‑distributed hashCode for keys and the cost of resizing, which depends on the load factor. Knowing these, the author now often initializes a map with an appropriate capacity, for example:
List<SomeBean> list = doSomeThing();
Map<Integer, String> map = new HashMap<>((int)(list.size() / 0.75)); // 0.75 is the default load factorWhen a map is heavily used, further optimizations involve ensuring custom key objects have fast, cached hashCode implementations and possibly lowering the load factor to trade more memory for speed.
Studying source code also cultivates the ability to generalize concepts: the author notes that any data structure backed by an array typically provides a capacity constructor, that space‑for‑time is a common algorithmic idea (e.g., bucket sort), and that database sharding or consistent hashing share similar principles.
Exploring other map implementations (TreeMap, LinkedHashMap, Hashtable, ConcurrentSkipListMap, ConcurrentHashMap) leads to the insight that sets are essentially maps, reducing the need to learn them separately.
Understanding underlying ideas is crucial; for instance, the author demystified the while‑loop in a CAS‑based method by examining its source:
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return prev;
}This reveals the distinction between optimistic locking (assuming no conflict and retrying on failure) and pessimistic locking (using synchronized or ReentrantLock), concepts that frequently appear in system integration design.
The core message is to spend most of the time learning the implementation principles behind code rather than merely using frameworks—"first cultivate inner skill, then practice techniques."
A complete request flow from front‑end to back‑end involves many technologies: JavaScript, HTML, CSS, AJAX (including cross‑origin issues), web caching, Nginx/Apache, authentication, cookies, sessions, Servlets, Filters, core data structures, thread pools, concurrency utilities, caching, I/O, etc. Understanding how each piece works is essential.
The author lists typical interview topics that reflect this depth: various Map types and their use‑cases, factors affecting HashMap performance, thread‑safe maps and ConcurrentHashMap internals, lock types, fair/read‑write locks, where synchronized can be applied, deadlock conditions, atomic object principles, ReentrantLock and Condition usage, volatile memory semantics, ThreadLocal mechanics, synchronization aids (CountDownLatch, CyclicBarrier, Semaphore), thread‑pool varieties, dynamic proxies, reflection, session vs. cookie handling, distributed session design, Nginx/Apache roles, AJAX cross‑origin solutions, JSONP basics, web optimization, and front‑end caching strategies.
In conclusion, continuous learning and building a systematic knowledge base—focusing on the "inner skill" of understanding implementations—allows beginners to progress quickly, apply concepts across domains, and ultimately master both the "功" (fundamentals) and the "拳" (frameworks) of Java development.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
