Flashcards for topic General Programming
Why is Math.abs(rnd.nextInt()) % n
a deeply flawed approach for generating random numbers in a range?
The Math.abs(rnd.nextInt()) % n
approach has three critical flaws:
Poor distribution: If n is not a power of 2, some numbers will appear more frequently than others. For example, with the code, approximately 2/3 of generated numbers will fall in the lower half of the range.
Short period for small ranges: If n is a small power of two, the sequence will repeat after a relatively short period.
Out-of-range error: If nextInt()
returns Integer.MIN_VALUE
, Math.abs()
will also return Integer.MIN_VALUE
(due to two's complement arithmetic), and the modulo operation can produce a negative result.
Instead, use standard library methods:
// For single-threaded contexts (Java 7+) ThreadLocalRandom.current().nextInt(0, n); // Exclusive upper bound // For parallel streams or fork-join pools SplittableRandom random = new SplittableRandom(); random.nextInt(0, n); // Exclusive upper bound
What makes for-each loops superior to traditional for loops, and what are the specific scenarios where you cannot use for-each loops?
Advantages of for-each loops:
Scenarios where for-each loops cannot be used:
Destructive filtering: When you need to remove elements during iteration
// Must use explicit iterator for removal for (Iterator<Element> i = c.iterator(); i.hasNext(); ) { Element e = i.next(); if (shouldRemove(e)) { i.remove(); // Cannot access remove() with for-each } } // Alternative in Java 8+: c.removeIf(e -> shouldRemove(e));
Transforming: When you need to replace elements in a collection/array
// Need index/iterator to modify collection for (int i = 0; i < list.size(); i++) { list.set(i, transform(list.get(i))); }
Parallel iteration: When you need to traverse multiple collections simultaneously
// Need explicit control of both iterators for (Iterator<A> i = a.iterator(), j = b.iterator(); i.hasNext() && j.hasNext(); ) { processSimultaneously(i.next(), j.next()); }
What is the optimal technique for minimizing scope in loops that involve expensive computations in their termination conditions?
The optimal technique is to use a "hoisted" double variable declaration in the for loop initialization:
// Efficient loop with hoisted limit computation for (int i = 0, n = expensiveComputation(); i < n; i++) { // Do something with i }
Key benefits:
This pattern should be used whenever:
This technique provides both a performance optimization and scope minimization in a single solution.
Explain the specific dangers when a local variable is declared prematurely (before it's used) in Java code.
Premature variable declaration creates several dangerous problems:
Scope expansion: The variable remains visible beyond its intended usage region
String value; // Premature declaration if (condition) { value = "something"; // Use value appropriately here } // value is still in scope here, creating possible misuse opportunities
Unintentional use: Variables may be accidentally used before initialization
int x; // Declared but not initialized // Complex logic... x++; // Accidental use before initialization - compiler error
Cognitive burden: Readers must remember the type and purpose of the variable between declaration and first use
Initialization delay: Proper initialization may be forgotten or incorrectly performed
Stale references: Objects remain referenced longer than necessary, potentially delaying garbage collection
The proper approach is:
// In the original scope if (condition) { String value = "something"; // Declared precisely where needed // Use value } // value goes out of scope exactly when no longer needed
What problematic design pattern can occur when using while loops for iteration, and why does this pattern lead to bugs that might be difficult to detect?
The problematic pattern with while loops is the "iterator leakage" anti-pattern:
// Problematic while loop pattern Iterator<Element> i = c.iterator(); while (i.hasNext()) { doSomething(i.next()); } ... // Later in code Iterator<Element> i2 = c2.iterator(); // New iterator while (i.hasNext()) { // BUG! Using original iterator 'i' instead of 'i2' doSomethingElse(i2.next()); }
This pattern is dangerous because:
Why it's hard to detect:
For-each loops eliminate this issue entirely by limiting the scope of iteration variables:
// For-each loops prevent this bug completely for (Element e : c) { doSomething(e); } for (Element e : c2) { // Completely separate variable scope doSomethingElse(e); }
What are the most effective techniques for minimizing the scope of local variables in Java, and how do they specifically improve code quality?
Techniques for Minimizing Variable Scope:
Declare variables at point of first use
// Instead of declaring at method start void process() { // Only declare when needed for (Element e : collection) { String formatted = e.toString(); // Declared exactly when needed // Use formatted } }
Prefer for loops over while loops
// For loop constrains iterator scope for (Iterator<Element> i = c.iterator(); i.hasNext(); ) { Element e = i.next(); // i and e only exist in this block }
Use for-each loops whenever possible
// Cleanest approach with minimum scope for (Element e : elements) { // e only exists here }
Create small, focused methods
// Split large methods into smaller ones void process() { loadData(); transformData(); saveResults(); }
Use hoisted loop limit calculations
for (int i = 0, n = expensiveComputation(); i < n; i++) { // Both i and n have minimum scope }
Benefits to Code Quality:
What are the key considerations when choosing between BigDecimal, int, and long for monetary calculations?
Choosing between number types for monetary calculations:
BigDecimal:
// Correct: uses String constructor BigDecimal value = new BigDecimal("10.25"); // Incorrect: introduces floating-point imprecision BigDecimal value = new BigDecimal(10.25);
int/long:
Selection guidelines:
What is the optimal implementation of a ThreadLocal that addresses all the shortcomings of the string-based and capability-based approaches?
A parameterized class that combines type safety with instance methods:
public final class ThreadLocal<T> { public ThreadLocal(); public void set(T value); public T get(); }
This implementation:
What are the legitimate cases where it's appropriate to use a class rather than an interface as a reference type?
Three legitimate cases:
General rule: Always use the least specific type in the hierarchy that provides the required functionality.
What are the three primary disadvantages of using reflection?
These disadvantages make reflection suitable only for specific use cases where the flexibility is absolutely required.
Showing 10 of 44 cards. Add this deck to your collection to see all cards.