Copy docker run --rm zchencow/innozverse-java:latest sh -c "
cat > /tmp/Lab01c.java << 'EOF'
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;
public class Lab01c {
record Product(int id, String name, String category, double price, int stock) {}
public static void main(String[] args) throws Exception {
var products = List.of(
new Product(1,\"Surface Pro\", \"Laptop\", 864.0, 15),
new Product(2,\"Surface Pen\", \"Accessory\", 49.99, 80),
new Product(3,\"Office 365\", \"Software\", 99.99,999),
new Product(4,\"USB-C Hub\", \"Hardware\", 29.99, 0),
new Product(5,\"Surface Book\", \"Laptop\", 1299.0, 5)
);
// Step 3: Multiple comparator chains
System.out.println(\"=== Multi-key Sort ===\" );
products.stream()
.sorted(Comparator.comparing(Product::category)
.thenComparing(Comparator.comparingDouble(Product::price).reversed()))
.forEach(p -> System.out.printf(\" %-12s %-15s \$%.2f%n\", p.category(), p.name(), p.price()));
// Step 4: computeIfAbsent — group products
System.out.println(\"\\n=== computeIfAbsent (group by category) ===\");
var grouped = new LinkedHashMap<String, List<Product>>();
products.forEach(p -> grouped.computeIfAbsent(p.category(), k -> new ArrayList<>()).add(p));
grouped.forEach((cat, list) ->
System.out.println(\" \" + cat + \": \" + list.stream().map(Product::name).toList()));
// Step 5: frequency map with merge
System.out.println(\"\\n=== Word Frequency (merge) ===\");
var words = List.of(\"surface\",\"pro\",\"surface\",\"pen\",\"office\",\"surface\",\"book\");
var freq = new LinkedHashMap<String, Integer>();
words.forEach(w -> freq.merge(w, 1, Integer::sum));
freq.entrySet().stream()
.sorted(Map.Entry.<String,Integer>comparingByValue().reversed())
.forEach(e -> System.out.println(\" \" + e.getKey() + \": \" + e.getValue()));
// Step 6: Unmodifiable & immutable views
System.out.println(\"\\n=== Immutable Collections ===\");
var immutableList = List.copyOf(products);
var immutableMap = Map.copyOf(freq);
System.out.println(\"immutableList size: \" + immutableList.size());
System.out.println(\"immutableMap keys: \" + new TreeSet<>(immutableMap.keySet()));
try { immutableList.add(null); }
catch (UnsupportedOperationException e) { System.out.println(\"Add blocked: \" + e.getClass().getSimpleName()); }
// Step 7: ConcurrentHashMap for thread-safe ops
System.out.println(\"\\n=== ConcurrentHashMap ===\");
var concurrent = new ConcurrentHashMap<String, Integer>();
var executor = Executors.newFixedThreadPool(4);
var latch = new java.util.concurrent.CountDownLatch(100);
for (int i = 0; i < 100; i++) {
final String key = \"item-\" + (i % 5);
executor.submit(() -> { concurrent.merge(key, 1, Integer::sum); latch.countDown(); });
}
latch.await(2, TimeUnit.SECONDS);
executor.shutdown();
int total = concurrent.values().stream().mapToInt(Integer::intValue).sum();
System.out.println(\" Total counts (should be 100): \" + total);
concurrent.entrySet().stream().sorted(Map.Entry.comparingByKey())
.forEach(e -> System.out.println(\" \" + e.getKey() + \" → \" + e.getValue()));
// Step 8: Capstone — inventory dashboard
System.out.println(\"\\n=== Inventory Dashboard ===\");
var byCategory = products.stream().collect(
Collectors.groupingBy(Product::category,
Collectors.summarizingDouble(p -> p.price() * p.stock())));
byCategory.entrySet().stream()
.sorted(Map.Entry.<String, DoubleSummaryStatistics>comparingByValue(
Comparator.comparingDouble(DoubleSummaryStatistics::getSum)).reversed())
.forEach(e -> System.out.printf(\" %-12s count=%d value=\$%,.2f%n\",
e.getKey(), e.getValue().getCount(), e.getValue().getSum()));
double grand = products.stream().mapToDouble(p->p.price()*p.stock()).sum();
System.out.printf(\" %-12s %s value=\$%,.2f%n\", \"TOTAL\", \" \", grand);
}
}
EOF
javac /tmp/Lab01c.java -d /tmp && java -cp /tmp Lab01c"