Flashcards for topic General Programming
What key problem occurs when using nested traditional for loops with iterators?
When using nested traditional for loops with iterators, calling next()
in both the outer and inner loops can lead to premature iterator exhaustion.
Example bug:
// BUG: Incorrect nested iteration for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) { for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); ) { deck.add(new Card(i.next(), j.next())); // i.next() called for each card! } }
The outer collection iterator (i.next()
) is called from the inner loop, exhausting it after just a few iterations. This often results in:
NoSuchElementException
if outer collection is smallerCorrect solution:
// Fixed approach for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) { Suit suit = i.next(); // Call next() ONCE per outer iteration for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); ) { deck.add(new Card(suit, j.next())); } }
What counterintuitive problem might occur when using try-catch blocks with variables initialized from expressions that can throw checked exceptions?
When a variable is initialized from an expression that can throw a checked exception, it creates a scope management challenge:
// Problem: Need variable both in and outside try block try { InputStream fileIn = new FileInputStream("myFile.txt"); // Use fileIn fileIn.close(); // Close in same block } catch (IOException e) { // Handle exception } // Cannot use fileIn here
If you need to use the variable outside the try block, you face a dilemma:
If you declare outside but initialize inside the try:
InputStream fileIn = null; // Must be declared before try try { fileIn = new FileInputStream("myFile.txt"); // Init in try // Use fileIn } catch (IOException e) { // Handle exception } // Can use fileIn here, but must check for null if (fileIn != null) { /* ... */ }
The variable can't be "sensibly initialized" outside the try block and must be checked for null
Best solution (Java 7+) using try-with-resources:
try (InputStream fileIn = new FileInputStream("myFile.txt")) { // Use fileIn } catch (IOException e) { // Handle exception } // fileIn not needed outside, automatically closed
What fundamental problem occurs when using float
or double
for monetary calculations, and why does it happen?
1.03 - 0.42
evaluates to 0.6100000000000001
instead of 0.61
1.00 - 9 * 0.10
evaluates to $0.09999999999999998
instead of $0.10
For exact monetary calculations, use:
BigDecimal
with String constructor (not double constructor)int
or long
(tracking cents or smallest unit)What is the correct approach to performance optimization in Java, and in what order should steps be taken?
Proper performance optimization process:
Remember: "Strive to write good programs rather than fast ones. If a good program is not fast enough, its architecture will allow it to be optimized."
What dangers arise from mixing primitives and boxed primitives in operations, and how can you prevent these issues?
Dangers of mixing primitives and boxed primitives:
Unexpected NullPointerException
Integer nullInteger = null; int value = nullInteger; // Throws NullPointerException during auto-unboxing
Identity comparison issues
==
on boxed primitives performs reference comparison, not value comparisonInteger a = 127; Integer b = 127; System.out.println(a == b); // May print true (due to caching) Integer c = 1000; Integer d = 1000; System.out.println(c == d); // Will print false (different objects)
Performance degradation
Prevention strategies:
Prefer primitives whenever possible
// Good long sum = 0L; // Bad Long sum = 0L;
Be explicit about unboxing when working with potentially null values
// Safer approach with null check if (boxedValue != null && boxedValue.intValue() > 0) {...}
Use proper value comparison for boxed primitives
// For equality: if (Integer.valueOf(42).equals(otherInteger)) {...} // For ordering: if (Integer.compare(a, b) < 0) {...}
Be consistent with variable types in arithmetic expressions
// All primitives int a = 1; int b = 2; int c = a + b; // All boxed Integer x = Integer.valueOf(1); Integer y = Integer.valueOf(2); Integer z = Integer.valueOf(x.intValue() + y.intValue());
How should objects be correctly referenced in variable declarations to maximize flexibility?
Good practice:
// Good - uses interface as type Set<String> itemSet = new LinkedHashSet<>();
Poor practice:
// Bad - uses implementation class as type LinkedHashSet<String> itemSet = new LinkedHashSet<>();
Benefits:
Implementation changes only require updating the constructor call, not all variable declarations throughout the codebase.
What is the best limited approach to using reflection that minimizes its drawbacks?
Limited Reflection Pattern:
Example approach:
// Use reflection only to create the instance Class<? extends Set<String>> cl = (Class<? extends Set<String>>) Class.forName(className); Constructor<? extends Set<String>> cons = cl.getDeclaredConstructor(); Set<String> set = cons.newInstance(); // Then use normal interface methods (no more reflection) set.addAll(elements); set.remove(element);
Benefits:
Compare the time complexity and performance characteristics of string concatenation versus StringBuilder for combining n strings, and explain why the difference exists.
String Concatenation vs. StringBuilder:
String concatenation in a loop:
StringBuilder approach:
Why the difference exists:
Performance example: For 100 strings of 80 characters each:
Even with Java compiler optimizations for string concatenation, the difference remains substantial for loops and large operations.
Explain the BigInteger implementation history and what it teaches about native methods for performance
Key lesson: While native implementations initially seemed faster, pure Java implementations eventually matched or exceeded performance while maintaining safety and portability. However, for specialized domains, native libraries may still offer advantages when they evolve more rapidly.
What are the performance implications of string concatenation in Java, and how should string building be implemented correctly in different scenarios?
+
operator) creates a new string object+
is fine:
Required for:
Implementation Pattern:
// Good performance - O(n) StringBuilder builder = new StringBuilder(estimatedCapacity); // Pre-allocation is important for (int i = 0; i < numItems(); i++) { builder.append(lineForItem(i)); } return builder.toString();
builder.append(x).append(y)
Showing 10 of 44 cards. Add this deck to your collection to see all cards.