Generics
Wildcards
Flexible Type Arguments
Your method accepts List<Number> but caller has List<Integer>. It won't
compile - generics aren't covariant. Wildcards like List<? extends Number>
accept List of any Number subtype, enabling flexible APIs.
Unbounded wildcard
Accept any type.
Unbounded.java
Replay: real traced execution (multi-file project)
import java.util.*;
public class Unbounded {
public static void printList(List<?> list) {
System.out.print(" List: [");
for (int i = 0; i < list.size(); i++) {
if (i > 0) System.out.print(", ");
System.out.print(list.get(i));
}
System.out.println("]");
}
public static void main(String[] args) {
System.out.println("Unbounded wildcard:\n");
List<Integer> ints = Arrays.asList(1, 2, 3);
List<String> strs = Arrays.asList("a", "b", "c");
List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3);
printList(ints);
printList(strs);
printList(doubles);
// <?> means "list of unknown type"
// Can read elements as Object
// Cannot add elements (except null)
// Useful for methods that only read
System.out.println("\nSize check:");
class Utils {
public static int getSize(List<?> list) {
return list.size();
}
public static boolean isEmpty(List<?> list) {
return list.isEmpty();
}
}
System.out.println(" Size of ints: " + Utils.getSize(ints));
System.out.println(" Size of strs: " + Utils.getSize(strs));
System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));
System.out.println("\nClear list:");
class Clearer {
public static void clear(List<?> list) {
list.clear();
System.out.println(" List cleared, size: " + list.size());
}
}
List<String> temp = new ArrayList<>(Arrays.asList("x", "y", "z"));
System.out.println(" Before: " + temp);
Clearer.clear(temp);
System.out.println(" After: " + temp);
System.out.println("\nContains check:");
class Checker {
public static boolean contains(List<?> list, Object item) {
return list.contains(item);
}
public static void displayFirst(List<?> list) {
if (!list.isEmpty()) {
Object first = list.get(0); // Read as Object
System.out.println(" First: " + first);
}
}
}
int intSearch = 2;
System.out.println(" ints contains " + intSearch + ": " +
Checker.contains(ints, intSearch));
System.out.println(" strs contains 'x': " + Checker.contains(strs, "x"));
Checker.displayFirst(ints);
Checker.displayFirst(strs);
System.out.println("\nCopy to Object list:");
class Copier {
public static List<Object> toObjectList(List<?> source) {
List<Object> result = new ArrayList<>();
for (Object item : source) { // Can read as Object
result.add(item);
}
return result;
}
}
List<Integer> numbers = Arrays.asList(10, 20, 30);
List<Object> objects = Copier.toObjectList(numbers);
System.out.println(" Copied: " + objects);
System.out.println("\nLimitations:");
List<?> wildList = new ArrayList<String>();
// wildList.add("text"); // Compile error - can't add
// wildList.add(123); // Compile error - can't add
wildList.add(null); // Only null allowed
System.out.println(" Can only add null to List<?>");
System.out.println(" Size: " + wildList.size());
}
}
import java.util.*;
public class Unbounded {
public static void printList(List<?> list) {
System.out.print(" List: [");
for (int i = 0; i < list.size(); i++) {
if (i > 0) System.out.print(", ");
System.out.print(list.get(i));
}
System.out.println("]");
}
public static void main(String[] args) {
System.out.println("Unbounded wildcard:\n");
List<Integer> ints = Arrays.asList(1, 2, 3);
List<String> strs = Arrays.asList("a", "b", "c");
List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3);
printList(ints);
printList(strs);
printList(doubles);
// <?> means "list of unknown type"
// Can read elements as Object
// Cannot add elements (except null)
// Useful for methods that only read
System.out.println("\nSize check:");
class Utils {
public static int getSize(List<?> list) {
return list.size();
}
public static boolean isEmpty(List<?> list) {
return list.isEmpty();
}
}
System.out.println(" Size of ints: " + Utils.getSize(ints));
System.out.println(" Size of strs: " + Utils.getSize(strs));
System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));
System.out.println("\nClear list:");
class Clearer {
public static void clear(List<?> list) {
list.clear();
System.out.println(" List cleared, size: " + list.size());
}
}
List<String> temp = new ArrayList<>(Arrays.asList("x", "y", "z"));
System.out.println(" Before: " + temp);
Clearer.clear(temp);
System.out.println(" After: " + temp);
System.out.println("\nContains check:");
class Checker {
public static boolean contains(List<?> list, Object item) {
return list.contains(item);
}
public static void displayFirst(List<?> list) {
if (!list.isEmpty()) {
Object first = list.get(0); // Read as Object
System.out.println(" First: " + first);
}
}
}
int intSearch = 1;
System.out.println(" ints contains " + intSearch + ": " +
Checker.contains(ints, intSearch));
System.out.println(" strs contains 'x': " + Checker.contains(strs, "x"));
Checker.displayFirst(ints);
Checker.displayFirst(strs);
System.out.println("\nCopy to Object list:");
class Copier {
public static List<Object> toObjectList(List<?> source) {
List<Object> result = new ArrayList<>();
for (Object item : source) { // Can read as Object
result.add(item);
}
return result;
}
}
List<Integer> numbers = Arrays.asList(10, 20, 30);
List<Object> objects = Copier.toObjectList(numbers);
System.out.println(" Copied: " + objects);
System.out.println("\nLimitations:");
List<?> wildList = new ArrayList<String>();
// wildList.add("text"); // Compile error - can't add
// wildList.add(123); // Compile error - can't add
wildList.add(null); // Only null allowed
System.out.println(" Can only add null to List<?>");
System.out.println(" Size: " + wildList.size());
}
}
import java.util.*;
public class Unbounded {
public static void printList(List<?> list) {
System.out.print(" List: [");
for (int i = 0; i < list.size(); i++) {
if (i > 0) System.out.print(", ");
System.out.print(list.get(i));
}
System.out.println("]");
}
public static void main(String[] args) {
System.out.println("Unbounded wildcard:\n");
List<Integer> ints = Arrays.asList(1, 2, 3);
List<String> strs = Arrays.asList("a", "b", "c");
List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3);
printList(ints);
printList(strs);
printList(doubles);
// <?> means "list of unknown type"
// Can read elements as Object
// Cannot add elements (except null)
// Useful for methods that only read
System.out.println("\nSize check:");
class Utils {
public static int getSize(List<?> list) {
return list.size();
}
public static boolean isEmpty(List<?> list) {
return list.isEmpty();
}
}
System.out.println(" Size of ints: " + Utils.getSize(ints));
System.out.println(" Size of strs: " + Utils.getSize(strs));
System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));
System.out.println("\nClear list:");
class Clearer {
public static void clear(List<?> list) {
list.clear();
System.out.println(" List cleared, size: " + list.size());
}
}
List<String> temp = new ArrayList<>(Arrays.asList("x", "y", "z"));
System.out.println(" Before: " + temp);
Clearer.clear(temp);
System.out.println(" After: " + temp);
System.out.println("\nContains check:");
class Checker {
public static boolean contains(List<?> list, Object item) {
return list.contains(item);
}
public static void displayFirst(List<?> list) {
if (!list.isEmpty()) {
Object first = list.get(0); // Read as Object
System.out.println(" First: " + first);
}
}
}
int intSearch = 4;
System.out.println(" ints contains " + intSearch + ": " +
Checker.contains(ints, intSearch));
System.out.println(" strs contains 'x': " + Checker.contains(strs, "x"));
Checker.displayFirst(ints);
Checker.displayFirst(strs);
System.out.println("\nCopy to Object list:");
class Copier {
public static List<Object> toObjectList(List<?> source) {
List<Object> result = new ArrayList<>();
for (Object item : source) { // Can read as Object
result.add(item);
}
return result;
}
}
List<Integer> numbers = Arrays.asList(10, 20, 30);
List<Object> objects = Copier.toObjectList(numbers);
System.out.println(" Copied: " + objects);
System.out.println("\nLimitations:");
List<?> wildList = new ArrayList<String>();
// wildList.add("text"); // Compile error - can't add
// wildList.add(123); // Compile error - can't add
wildList.add(null); // Only null allowed
System.out.println(" Can only add null to List<?>");
System.out.println(" Size: " + wildList.size());
}
}
public static void main(String[] args)
13public static void main(String[] args) {14 System.out.println("Unbounded wildcard:\n");outputUnbounded wildcard: Unbounded wildcard:public static void printList(List<?> list)
pass 1 of 33public class Unbounded {4 public static void printList(List<?> list[1, 2, 3]) {5 System.out.print(" List: [");6 for (int i = 0; i < list.size(); i++) {output List: [All 3 passes — pass 1 is the card above pass list1 [1, 2, 3] 2 [a, b, c] 3 [1.1, 2.2, 3.3] for (int i = 0; i < list.size(); i++)
pass 1 of 95System.out.print(" List: [");6for (int i0 = 0; i < list.size(); i++) {7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i0));9}output1All 9 passes — pass 1 is the card above pass i1 0 2 1 3 2 4 0 5 1 6 2 7 0 8 1 9 2 if (i > 0)
pass 1 of 66for (int i = 0; i < list.size(); i++) {7 if (i1 > 0) System.out.print(", ");8 System.out.print(list.get(i));output,All 6 passes — pass 1 is the card above pass i1 1 2 2 3 1 4 2 5 1 6 2 System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i1));9}output2System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i2));9}output3System.out.println("]");
9 }10 System.out.println("]");11}output]System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i1));9}outputbSystem.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i2));9}outputcSystem.out.println("]");
9 }10 System.out.println("]");11}output]System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i1));9}output2.2System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i2));9}output3.3System.out.println("]");
9 }10 System.out.println("]");11}output]System.out.println(" Size check:");
29System.out.println("\nSize check:");output Size check: Size check:public static int getSize(List<?> list)
pass 1 of 331class Utils {32 public static int getSize(List<?> list[1, 2, 3]) {33 return list.size();34 }All 3 passes — pass 1 is the card above pass list1 [1, 2, 3] 2 [a, b, c] 3 [a, b, c] System.out.println(" Size of strs: " + Utils.getSize(strs));
41System.out.println(" Size of ints: " + Utils.getSize(ints));42System.out.println(" Size of strs: " + Utils.getSize(strs[a, b, c]));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));System.out.println(" Size of strs: " + Utils.getSize(strs));
41System.out.println(" Size of ints: " + Utils.getSize(ints));42System.out.println(" Size of strs: " + Utils.getSize(strs[a, b, c]));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));output Size of strs: 3System.out.println(" Size of strs: " + Utils.getSize(strs));
41System.out.println(" Size of ints: " + Utils.getSize(ints));42System.out.println(" Size of strs: " + Utils.getSize(strs[a, b, c]));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));output Size of strs: 3public static boolean isEmpty(List<?> list)
pass 1 of 236public static boolean isEmpty(List<?> list[]) {37 return list.isEmpty();38}System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));
42System.out.println(" Size of strs: " + Utils.getSize(strs));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));output Empty: truepublic static boolean isEmpty(List<?> list)
pass 2 of 236public static boolean isEmpty(List<?> list[]) {37 return list.isEmpty();38}System.out.println(" Before: " + temp);
42System.out.println(" Size of strs: " + Utils.getSize(strs));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));4445System.out.println("\nClear list:");4647class Clearer {48 public static void clear(List<?> list) {49 list.clear();50 System.out.println(" List cleared, size: " + list.size());51 }52}5354List<String> temp = new ArrayList<>(Arrays.asList("x", "y", "z"));55System.out.println(" Before: " + temp[x, y, z]);56Clearer.clear(temp);output Empty: true Clear list: Clear list: Before: [x, y, z] Before: [x, y, z]public static void clear(List<?> list)
47class Clearer {48 public static void clear(List<?> list[x, y, z]) {49 list.clear();50 System.out.println(" List cleared, size: " + list.size());51 }output List cleared, size: 0System.out.println(" After: " + temp);
56Clearer.clear(temp);57System.out.println(" After: " + temp[]);5859System.out.println("\nContains check:");6061class Checker {62 public static boolean contains(List<?> list, Object item) {63 return list.contains(item);64 }65 66 public static void displayFirst(List<?> list) {67 if (!list.isEmpty()) {68 Object first = list.get(0); // Read as Object69 System.out.println(" First: " + first);70 }71 }72}7374int intSearch = 2; //@intSearch=2, 1, 475System.out.println(" ints contains " + intSearch2 + ": " +76 Checker.contains(ints[1, 2, 3], intSearch2));77System.out.println(" strs contains 'x': " + Checker.contains(strs, "x"));output After: [] After: [] Contains check: Contains check:public static boolean contains(List<?> list, Object item)
pass 1 of 461class Checker {62 public static boolean contains(List<?> list[1, 2, 3], Object item2) {63 return list.contains(item2);64 }All 4 passes — pass 1 is the card above pass listitem1 [1, 2, 3] 2 2 [1, 2, 3] 2 3 [a, b, c] x 4 [a, b, c] x System.out.println(" ints contains " + intSearch + ": " +
74int intSearch = 2; //@intSearch=2, 1, 475System.out.println(" ints contains " + intSearch2 + ": " +76 Checker.contains(ints[1, 2, 3], intSearch2));77System.out.println(" strs contains 'x': " + Checker.contains(strs, "x"));output ints contains 2: trueSystem.out.println(" ints contains " + intSearch + ": " +
74int intSearch = 2; //@intSearch=2, 1, 475System.out.println(" ints contains " + intSearch2 + ": " +76 Checker.contains(ints[1, 2, 3], intSearch2));77System.out.println(" strs contains 'x': " + Checker.contains(strs[a, b, c], "x"));output ints contains 2: trueSystem.out.println(" strs contains 'x': " + Checker.contains(strs, "x…
76 Checker.contains(ints, intSearch));77System.out.println(" strs contains 'x': " + Checker.contains(strs[a, b, c], "x"));output strs contains 'x': falseSystem.out.println(" strs contains 'x': " + Checker.contains(strs, "x…
76 Checker.contains(ints, intSearch));77System.out.println(" strs contains 'x': " + Checker.contains(strs[a, b, c], "x"));output strs contains 'x': falsepublic static void displayFirst(List<?> list)
pass 1 of 266public static void displayFirst(List<?> list[1, 2, 3]) {67 if (!list.isEmpty()) {first ← 1
pass 1 of 266public static void displayFirst(List<?> list) {67 if (!list.isEmpty()) {68 Object first→ 1 = list.get(0); // Read as Object69 System.out.println(" First: " + first1);70 }output First: 1public static void displayFirst(List<?> list)
pass 2 of 266public static void displayFirst(List<?> list[a, b, c]) {67 if (!list.isEmpty()) {first ← a
pass 2 of 266public static void displayFirst(List<?> list) {67 if (!list.isEmpty()) {68 Object first→ a = list.get(0); // Read as Object69 System.out.println(" First: " + firsta);70 }output First: aList<Object> objects = Copier.toObjectList(numbers);
82System.out.println("\nCopy to Object list:");8384class Copier {85 public static List<Object> toObjectList(List<?> source) {86 List<Object> result = new ArrayList<>();87 for (Object item : source) { // Can read as Object88 result.add(item);89 }90 return result;91 }92}9394List<Integer> numbers = Arrays.asList(10, 20, 30);95List<Object> objects = Copier.toObjectList(numbers[10, 20, 30]);96System.out.println(" Copied: " + objects);output Copy to Object list: Copy to Object list:result ← []
84class Copier {85 public static List<Object> toObjectList(List<?> source[10, 20, 30]) {86 List<Object> result→ [] = new ArrayList<>();87 for (Object item : source) { // Can read as Objectfor (Object item : source)
pass 1 of 386List<Object> result = new ArrayList<>();87for (Object item10 : source[10, 20, 30]) { // Can read as Object88 result.add(item10);89}All 3 passes — pass 1 is the card above pass item1 10 2 20 3 30 return result;
89 }90 return result[10, 20, 30];91}objects ← [10, 20, 30], wildList ← []
94 List<Integer> numbers = Arrays.asList(10, 20, 30);95 List<Object> objects→ [10, 20, 30] = Copier.toObjectList(numbers[10, 20, 30]);96 System.out.println(" Copied: " + objects[10, 20, 30]);97 98 System.out.println("\nLimitations:");99 100 List<?> wildList→ [] = new ArrayList<String>();101 // wildList.add("text"); // Compile error - can't add102 // wildList.add(123); // Compile error - can't add103 wildList.add(null); // Only null allowed104 105 System.out.println(" Can only add null to List<?>");106 System.out.println(" Size: " + wildList.size());107}output Copied: [10, 20, 30] Limitations: Can only add null to List<?> Size: 1
public static void main(String[] args)
13public static void main(String[] args) {14 System.out.println("Unbounded wildcard:\n");outputUnbounded wildcard: Unbounded wildcard:public static void printList(List<?> list)
pass 1 of 33public class Unbounded {4 public static void printList(List<?> list[1, 2, 3]) {5 System.out.print(" List: [");6 for (int i = 0; i < list.size(); i++) {output List: [All 3 passes — pass 1 is the card above pass list1 [1, 2, 3] 2 [a, b, c] 3 [1.1, 2.2, 3.3] for (int i = 0; i < list.size(); i++)
pass 1 of 95System.out.print(" List: [");6for (int i0 = 0; i < list.size(); i++) {7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i0));9}output1All 9 passes — pass 1 is the card above pass i1 0 2 1 3 2 4 0 5 1 6 2 7 0 8 1 9 2 if (i > 0)
pass 1 of 66for (int i = 0; i < list.size(); i++) {7 if (i1 > 0) System.out.print(", ");8 System.out.print(list.get(i));output,All 6 passes — pass 1 is the card above pass i1 1 2 2 3 1 4 2 5 1 6 2 System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i1));9}output2System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i2));9}output3System.out.println("]");
9 }10 System.out.println("]");11}output]System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i1));9}outputbSystem.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i2));9}outputcSystem.out.println("]");
9 }10 System.out.println("]");11}output]System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i1));9}output2.2System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i2));9}output3.3System.out.println("]");
9 }10 System.out.println("]");11}output]System.out.println(" Size check:");
29System.out.println("\nSize check:");output Size check: Size check:public static int getSize(List<?> list)
pass 1 of 331class Utils {32 public static int getSize(List<?> list[1, 2, 3]) {33 return list.size();34 }All 3 passes — pass 1 is the card above pass list1 [1, 2, 3] 2 [a, b, c] 3 [a, b, c] System.out.println(" Size of strs: " + Utils.getSize(strs));
41System.out.println(" Size of ints: " + Utils.getSize(ints));42System.out.println(" Size of strs: " + Utils.getSize(strs[a, b, c]));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));System.out.println(" Size of strs: " + Utils.getSize(strs));
41System.out.println(" Size of ints: " + Utils.getSize(ints));42System.out.println(" Size of strs: " + Utils.getSize(strs[a, b, c]));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));output Size of strs: 3System.out.println(" Size of strs: " + Utils.getSize(strs));
41System.out.println(" Size of ints: " + Utils.getSize(ints));42System.out.println(" Size of strs: " + Utils.getSize(strs[a, b, c]));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));output Size of strs: 3public static boolean isEmpty(List<?> list)
pass 1 of 236public static boolean isEmpty(List<?> list[]) {37 return list.isEmpty();38}System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));
42System.out.println(" Size of strs: " + Utils.getSize(strs));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));output Empty: truepublic static boolean isEmpty(List<?> list)
pass 2 of 236public static boolean isEmpty(List<?> list[]) {37 return list.isEmpty();38}System.out.println(" Before: " + temp);
42System.out.println(" Size of strs: " + Utils.getSize(strs));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));4445System.out.println("\nClear list:");4647class Clearer {48 public static void clear(List<?> list) {49 list.clear();50 System.out.println(" List cleared, size: " + list.size());51 }52}5354List<String> temp = new ArrayList<>(Arrays.asList("x", "y", "z"));55System.out.println(" Before: " + temp[x, y, z]);56Clearer.clear(temp);output Empty: true Clear list: Clear list: Before: [x, y, z] Before: [x, y, z]public static void clear(List<?> list)
47class Clearer {48 public static void clear(List<?> list[x, y, z]) {49 list.clear();50 System.out.println(" List cleared, size: " + list.size());51 }output List cleared, size: 0System.out.println(" After: " + temp);
56Clearer.clear(temp);57System.out.println(" After: " + temp[]);5859System.out.println("\nContains check:");6061class Checker {62 public static boolean contains(List<?> list, Object item) {63 return list.contains(item);64 }65 66 public static void displayFirst(List<?> list) {67 if (!list.isEmpty()) {68 Object first = list.get(0); // Read as Object69 System.out.println(" First: " + first);70 }71 }72}7374int intSearch = 1;75System.out.println(" ints contains " + intSearch1 + ": " +76 Checker.contains(ints[1, 2, 3], intSearch1));77System.out.println(" strs contains 'x': " + Checker.contains(strs, "x"));output After: [] After: [] Contains check: Contains check:public static boolean contains(List<?> list, Object item)
pass 1 of 461class Checker {62 public static boolean contains(List<?> list[1, 2, 3], Object item1) {63 return list.contains(item1);64 }All 4 passes — pass 1 is the card above pass listitem1 [1, 2, 3] 1 2 [1, 2, 3] 1 3 [a, b, c] x 4 [a, b, c] x System.out.println(" ints contains " + intSearch + ": " +
74int intSearch = 1;75System.out.println(" ints contains " + intSearch1 + ": " +76 Checker.contains(ints[1, 2, 3], intSearch1));77System.out.println(" strs contains 'x': " + Checker.contains(strs, "x"));output ints contains 1: trueSystem.out.println(" ints contains " + intSearch + ": " +
74int intSearch = 1;75System.out.println(" ints contains " + intSearch1 + ": " +76 Checker.contains(ints[1, 2, 3], intSearch1));77System.out.println(" strs contains 'x': " + Checker.contains(strs[a, b, c], "x"));output ints contains 1: trueSystem.out.println(" strs contains 'x': " + Checker.contains(strs, "x…
76 Checker.contains(ints, intSearch));77System.out.println(" strs contains 'x': " + Checker.contains(strs[a, b, c], "x"));output strs contains 'x': falseSystem.out.println(" strs contains 'x': " + Checker.contains(strs, "x…
76 Checker.contains(ints, intSearch));77System.out.println(" strs contains 'x': " + Checker.contains(strs[a, b, c], "x"));output strs contains 'x': falsepublic static void displayFirst(List<?> list)
pass 1 of 266public static void displayFirst(List<?> list[1, 2, 3]) {67 if (!list.isEmpty()) {first ← 1
pass 1 of 266public static void displayFirst(List<?> list) {67 if (!list.isEmpty()) {68 Object first→ 1 = list.get(0); // Read as Object69 System.out.println(" First: " + first1);70 }output First: 1public static void displayFirst(List<?> list)
pass 2 of 266public static void displayFirst(List<?> list[a, b, c]) {67 if (!list.isEmpty()) {first ← a
pass 2 of 266public static void displayFirst(List<?> list) {67 if (!list.isEmpty()) {68 Object first→ a = list.get(0); // Read as Object69 System.out.println(" First: " + firsta);70 }output First: aList<Object> objects = Copier.toObjectList(numbers);
82System.out.println("\nCopy to Object list:");8384class Copier {85 public static List<Object> toObjectList(List<?> source) {86 List<Object> result = new ArrayList<>();87 for (Object item : source) { // Can read as Object88 result.add(item);89 }90 return result;91 }92}9394List<Integer> numbers = Arrays.asList(10, 20, 30);95List<Object> objects = Copier.toObjectList(numbers[10, 20, 30]);96System.out.println(" Copied: " + objects);output Copy to Object list: Copy to Object list:result ← []
84class Copier {85 public static List<Object> toObjectList(List<?> source[10, 20, 30]) {86 List<Object> result→ [] = new ArrayList<>();87 for (Object item : source) { // Can read as Objectfor (Object item : source)
pass 1 of 386List<Object> result = new ArrayList<>();87for (Object item10 : source[10, 20, 30]) { // Can read as Object88 result.add(item10);89}All 3 passes — pass 1 is the card above pass item1 10 2 20 3 30 return result;
89 }90 return result[10, 20, 30];91}objects ← [10, 20, 30], wildList ← []
94 List<Integer> numbers = Arrays.asList(10, 20, 30);95 List<Object> objects→ [10, 20, 30] = Copier.toObjectList(numbers[10, 20, 30]);96 System.out.println(" Copied: " + objects[10, 20, 30]);97 98 System.out.println("\nLimitations:");99 100 List<?> wildList→ [] = new ArrayList<String>();101 // wildList.add("text"); // Compile error - can't add102 // wildList.add(123); // Compile error - can't add103 wildList.add(null); // Only null allowed104 105 System.out.println(" Can only add null to List<?>");106 System.out.println(" Size: " + wildList.size());107}output Copied: [10, 20, 30] Limitations: Can only add null to List<?> Size: 1
public static void main(String[] args)
13public static void main(String[] args) {14 System.out.println("Unbounded wildcard:\n");outputUnbounded wildcard: Unbounded wildcard:public static void printList(List<?> list)
pass 1 of 33public class Unbounded {4 public static void printList(List<?> list[1, 2, 3]) {5 System.out.print(" List: [");6 for (int i = 0; i < list.size(); i++) {output List: [All 3 passes — pass 1 is the card above pass list1 [1, 2, 3] 2 [a, b, c] 3 [1.1, 2.2, 3.3] for (int i = 0; i < list.size(); i++)
pass 1 of 95System.out.print(" List: [");6for (int i0 = 0; i < list.size(); i++) {7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i0));9}output1All 9 passes — pass 1 is the card above pass i1 0 2 1 3 2 4 0 5 1 6 2 7 0 8 1 9 2 if (i > 0)
pass 1 of 66for (int i = 0; i < list.size(); i++) {7 if (i1 > 0) System.out.print(", ");8 System.out.print(list.get(i));output,All 6 passes — pass 1 is the card above pass i1 1 2 2 3 1 4 2 5 1 6 2 System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i1));9}output2System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i2));9}output3System.out.println("]");
9 }10 System.out.println("]");11}output]System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i1));9}outputbSystem.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i2));9}outputcSystem.out.println("]");
9 }10 System.out.println("]");11}output]System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i1));9}output2.2System.out.print(list.get(i));
7 if (i > 0) System.out.print(", ");8 System.out.print(list.get(i2));9}output3.3System.out.println("]");
9 }10 System.out.println("]");11}output]System.out.println(" Size check:");
29System.out.println("\nSize check:");output Size check: Size check:public static int getSize(List<?> list)
pass 1 of 331class Utils {32 public static int getSize(List<?> list[1, 2, 3]) {33 return list.size();34 }All 3 passes — pass 1 is the card above pass list1 [1, 2, 3] 2 [a, b, c] 3 [a, b, c] System.out.println(" Size of strs: " + Utils.getSize(strs));
41System.out.println(" Size of ints: " + Utils.getSize(ints));42System.out.println(" Size of strs: " + Utils.getSize(strs[a, b, c]));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));System.out.println(" Size of strs: " + Utils.getSize(strs));
41System.out.println(" Size of ints: " + Utils.getSize(ints));42System.out.println(" Size of strs: " + Utils.getSize(strs[a, b, c]));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));output Size of strs: 3System.out.println(" Size of strs: " + Utils.getSize(strs));
41System.out.println(" Size of ints: " + Utils.getSize(ints));42System.out.println(" Size of strs: " + Utils.getSize(strs[a, b, c]));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));output Size of strs: 3public static boolean isEmpty(List<?> list)
pass 1 of 236public static boolean isEmpty(List<?> list[]) {37 return list.isEmpty();38}System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));
42System.out.println(" Size of strs: " + Utils.getSize(strs));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));output Empty: truepublic static boolean isEmpty(List<?> list)
pass 2 of 236public static boolean isEmpty(List<?> list[]) {37 return list.isEmpty();38}System.out.println(" Before: " + temp);
42System.out.println(" Size of strs: " + Utils.getSize(strs));43System.out.println(" Empty: " + Utils.isEmpty(new ArrayList<>()));4445System.out.println("\nClear list:");4647class Clearer {48 public static void clear(List<?> list) {49 list.clear();50 System.out.println(" List cleared, size: " + list.size());51 }52}5354List<String> temp = new ArrayList<>(Arrays.asList("x", "y", "z"));55System.out.println(" Before: " + temp[x, y, z]);56Clearer.clear(temp);output Empty: true Clear list: Clear list: Before: [x, y, z] Before: [x, y, z]public static void clear(List<?> list)
47class Clearer {48 public static void clear(List<?> list[x, y, z]) {49 list.clear();50 System.out.println(" List cleared, size: " + list.size());51 }output List cleared, size: 0System.out.println(" After: " + temp);
56Clearer.clear(temp);57System.out.println(" After: " + temp[]);5859System.out.println("\nContains check:");6061class Checker {62 public static boolean contains(List<?> list, Object item) {63 return list.contains(item);64 }65 66 public static void displayFirst(List<?> list) {67 if (!list.isEmpty()) {68 Object first = list.get(0); // Read as Object69 System.out.println(" First: " + first);70 }71 }72}7374int intSearch = 4;75System.out.println(" ints contains " + intSearch4 + ": " +76 Checker.contains(ints[1, 2, 3], intSearch4));77System.out.println(" strs contains 'x': " + Checker.contains(strs, "x"));output After: [] After: [] Contains check: Contains check:public static boolean contains(List<?> list, Object item)
pass 1 of 461class Checker {62 public static boolean contains(List<?> list[1, 2, 3], Object item4) {63 return list.contains(item4);64 }All 4 passes — pass 1 is the card above pass listitem1 [1, 2, 3] 4 2 [1, 2, 3] 4 3 [a, b, c] x 4 [a, b, c] x System.out.println(" ints contains " + intSearch + ": " +
74int intSearch = 4;75System.out.println(" ints contains " + intSearch4 + ": " +76 Checker.contains(ints[1, 2, 3], intSearch4));77System.out.println(" strs contains 'x': " + Checker.contains(strs, "x"));output ints contains 4: falseSystem.out.println(" ints contains " + intSearch + ": " +
74int intSearch = 4;75System.out.println(" ints contains " + intSearch4 + ": " +76 Checker.contains(ints[1, 2, 3], intSearch4));77System.out.println(" strs contains 'x': " + Checker.contains(strs[a, b, c], "x"));output ints contains 4: falseSystem.out.println(" strs contains 'x': " + Checker.contains(strs, "x…
76 Checker.contains(ints, intSearch));77System.out.println(" strs contains 'x': " + Checker.contains(strs[a, b, c], "x"));output strs contains 'x': falseSystem.out.println(" strs contains 'x': " + Checker.contains(strs, "x…
76 Checker.contains(ints, intSearch));77System.out.println(" strs contains 'x': " + Checker.contains(strs[a, b, c], "x"));output strs contains 'x': falsepublic static void displayFirst(List<?> list)
pass 1 of 266public static void displayFirst(List<?> list[1, 2, 3]) {67 if (!list.isEmpty()) {first ← 1
pass 1 of 266public static void displayFirst(List<?> list) {67 if (!list.isEmpty()) {68 Object first→ 1 = list.get(0); // Read as Object69 System.out.println(" First: " + first1);70 }output First: 1public static void displayFirst(List<?> list)
pass 2 of 266public static void displayFirst(List<?> list[a, b, c]) {67 if (!list.isEmpty()) {first ← a
pass 2 of 266public static void displayFirst(List<?> list) {67 if (!list.isEmpty()) {68 Object first→ a = list.get(0); // Read as Object69 System.out.println(" First: " + firsta);70 }output First: aList<Object> objects = Copier.toObjectList(numbers);
82System.out.println("\nCopy to Object list:");8384class Copier {85 public static List<Object> toObjectList(List<?> source) {86 List<Object> result = new ArrayList<>();87 for (Object item : source) { // Can read as Object88 result.add(item);89 }90 return result;91 }92}9394List<Integer> numbers = Arrays.asList(10, 20, 30);95List<Object> objects = Copier.toObjectList(numbers[10, 20, 30]);96System.out.println(" Copied: " + objects);output Copy to Object list: Copy to Object list:result ← []
84class Copier {85 public static List<Object> toObjectList(List<?> source[10, 20, 30]) {86 List<Object> result→ [] = new ArrayList<>();87 for (Object item : source) { // Can read as Objectfor (Object item : source)
pass 1 of 386List<Object> result = new ArrayList<>();87for (Object item10 : source[10, 20, 30]) { // Can read as Object88 result.add(item10);89}All 3 passes — pass 1 is the card above pass item1 10 2 20 3 30 return result;
89 }90 return result[10, 20, 30];91}objects ← [10, 20, 30], wildList ← []
94 List<Integer> numbers = Arrays.asList(10, 20, 30);95 List<Object> objects→ [10, 20, 30] = Copier.toObjectList(numbers[10, 20, 30]);96 System.out.println(" Copied: " + objects[10, 20, 30]);97 98 System.out.println("\nLimitations:");99 100 List<?> wildList→ [] = new ArrayList<String>();101 // wildList.add("text"); // Compile error - can't add102 // wildList.add(123); // Compile error - can't add103 wildList.add(null); // Only null allowed104 105 System.out.println(" Can only add null to List<?>");106 System.out.println(" Size: " + wildList.size());107}output Copied: [10, 20, 30] Limitations: Can only add null to List<?> Size: 1
List<?> accepts List of any type. Can only read as Object.
unbounded wildcard
`<?>` matches any type. Read-only for practical purposes.
Upper bounded wildcard
Accept type or subtypes.
UpperBound.java
Replay: real traced execution (multi-file project)
import java.util.*;
public class UpperBound {
public static double sum(List<? extends Number> numbers) {
double total = 0;
for (Number num : numbers) { // Can read as Number
total += num.doubleValue();
}
return total;
}
public static void main(String[] args) {
System.out.println("Upper bounded wildcard:\n");
List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5);
List<Double> doubles = Arrays.asList(1.5, 2.5, 3.5);
List<Long> longs = Arrays.asList(10L, 20L, 30L);
System.out.println(" Sum ints: " + sum(ints));
System.out.println(" Sum doubles: " + sum(doubles));
System.out.println(" Sum longs: " + sum(longs));
// <? extends T> means "unknown type that extends T"
// Can read elements as T
// Cannot add elements (except null) - don't know exact type
// PECS: Producer Extends - use when reading/producing
System.out.println("\nFind max:");
class Finder {
public static <T extends Comparable<T>> T max(
List<? extends T> list) {
if (list.isEmpty()) {
return null;
}
T max = list.get(0);
for (T item : list) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
}
System.out.println(" Max int: " + Finder.max(ints));
System.out.println(" Max double: " + Finder.max(doubles));
List<String> words = Arrays.asList("apple", "zebra", "banana");
System.out.println(" Max string: " + Finder.max(words));
System.out.println("\nCopy numbers:");
class Copier {
public static void copyNumbers(
List<? extends Number> source,
List<Number> dest) {
dest.clear();
for (Number num : source) { // Read as Number
dest.add(num);
}
}
}
List<Number> result = new ArrayList<>();
Copier.copyNumbers(ints, result);
System.out.println(" Copied: " + result);
System.out.println("\nAverage:");
class Stats {
public static double average(List<? extends Number> numbers) {
if (numbers.isEmpty()) {
return 0;
}
return sum(numbers) / numbers.size();
}
public static Number min(List<? extends Number> numbers) {
if (numbers.isEmpty()) {
return null;
}
double minVal = numbers.get(0).doubleValue();
Number min = numbers.get(0);
for (Number num : numbers) {
if (num.doubleValue() < minVal) {
minVal = num.doubleValue();
min = num;
}
}
return min;
}
}
System.out.println(" Average: " + Stats.average(ints));
System.out.println(" Min: " + Stats.min(doubles));
System.out.println("\nPrint comparable:");
class Printer {
public static <T extends Comparable<T>> void printSorted(
List<? extends T> list) {
List<T> copy = new ArrayList<>(list);
Collections.sort(copy);
System.out.print(" Sorted: ");
for (T item : copy) {
System.out.print(item + " ");
}
System.out.println();
}
}
Printer.printSorted(Arrays.asList(5, 1, 9, 3, 7));
Printer.printSorted(Arrays.asList("dog", "cat", "ant", "bee"));
System.out.println("\nLimitations:");
List<? extends Number> numList = new ArrayList<Integer>();
// numList.add(1); // Compile error
// numList.add(1.5); // Compile error
// numList.add(new Integer(1)); // Compile error
System.out.println(" Cannot add to List<? extends Number>");
System.out.println(" Reason: Don't know if it's Integer, Double, etc.");
}
}
public static void main(String[] args)
12public static void main(String[] args) {13 System.out.println("Upper bounded wildcard:\n");14 15 List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5);16 List<Double> doubles = Arrays.asList(1.5, 2.5, 3.5);17 List<Long> longs = Arrays.asList(10L, 20L, 30L);18 19 System.out.println(" Sum ints: " + sum(ints[1, 2, 3, 4, 5]));20 System.out.println(" Sum doubles: " + sum(doubles));outputUpper bounded wildcard: Upper bounded wildcard:total ← 0.0
pass 1 of 73public class UpperBound {4 public static double sum(List<? extends Number> numbers[1, 2, 3, 4, 5]) {5 double total→ 0.0 = 0;6 for (Number num : numbers) { // Can read as NumberAll 7 passes — pass 1 is the card above pass numberstotal1 [1, 2, 3, 4, 5] 0.0 2 [1, 2, 3, 4, 5] 0.0 3 [1.5, 2.5, 3.5] 0.0 4 [1.5, 2.5, 3.5] 0.0 5 [10, 20, 30] 0.0 6 [10, 20, 30] 0.0 7 [1, 2, 3, 4, 5] 0.0 total ← 1.0
pass 1 of 275double total = 0;6for (Number num1 : numbers[1, 2, 3, 4, 5]) { // Can read as Number7 total→ 1.0 += num.doubleValue();8}27 passes — pass 1 is the card above pass numnumberstotal1 1 [1, 2, 3, 4, 5] 0.0 → 1.0 2 2 [1, 2, 3, 4, 5] 1.0 → 3.0 3 3 [1, 2, 3, 4, 5] 3.0 → 6.0 4 4 [1, 2, 3, 4, 5] 6.0 → 10.0 5 5 [1, 2, 3, 4, 5] 10.0 → 15.0 6 1 [1, 2, 3, 4, 5] 0.0 → 1.0 7 2 [1, 2, 3, 4, 5] 1.0 → 3.0 8 3 [1, 2, 3, 4, 5] 3.0 → 6.0 9 4 [1, 2, 3, 4, 5] 6.0 → 10.0 ⋯ 16 more passes ⋯ 26 4 [1, 2, 3, 4, 5] 6.0 → 10.0 27 5 [1, 2, 3, 4, 5] 10.0 → 15.0 return total;
8 }9 return total15.0;10}System.out.println(" Sum ints: " + sum(ints));
19System.out.println(" Sum ints: " + sum(ints[1, 2, 3, 4, 5]));20System.out.println(" Sum doubles: " + sum(doubles));output Sum ints: 15.0return total;
8 }9 return total15.0;10}System.out.println(" Sum ints: " + sum(ints));
19System.out.println(" Sum ints: " + sum(ints[1, 2, 3, 4, 5]));20System.out.println(" Sum doubles: " + sum(doubles[1.5, 2.5, 3.5]));21System.out.println(" Sum longs: " + sum(longs));output Sum ints: 15.0return total;
8 }9 return total7.5;10}System.out.println(" Sum doubles: " + sum(doubles));
19System.out.println(" Sum ints: " + sum(ints));20System.out.println(" Sum doubles: " + sum(doubles[1.5, 2.5, 3.5]));21System.out.println(" Sum longs: " + sum(longs));output Sum doubles: 7.5return total;
8 }9 return total7.5;10}System.out.println(" Sum doubles: " + sum(doubles));
19System.out.println(" Sum ints: " + sum(ints));20System.out.println(" Sum doubles: " + sum(doubles[1.5, 2.5, 3.5]));21System.out.println(" Sum longs: " + sum(longs[10, 20, 30]));output Sum doubles: 7.5return total;
8 }9 return total60.0;10}System.out.println(" Sum longs: " + sum(longs));
20System.out.println(" Sum doubles: " + sum(doubles));21System.out.println(" Sum longs: " + sum(longs[10, 20, 30]));output Sum longs: 60.0return total;
8 }9 return total60.0;10}System.out.println(" Sum longs: " + sum(longs));
20System.out.println(" Sum doubles: " + sum(doubles));21System.out.println(" Sum longs: " + sum(longs[10, 20, 30]));2223// <? extends T> means "unknown type that extends T"24// Can read elements as T25// Cannot add elements (except null) - don't know exact type26// PECS: Producer Extends - use when reading/producing2728System.out.println("\nFind max:");output Sum longs: 60.0 Find max: Find max:max ← 1
pass 1 of 530class Finder {31 public static <T extends Comparable<T>> T max(32 List<? extends T> list[1, 2, 3, 4, 5]) {33 if (list.isEmpty()) {34 return null;35 }36 37 T max→ 1 = list.get(0);38 for (T item : list) {All 5 passes — pass 1 is the card above pass listmax1 [1, 2, 3, 4, 5] 1 2 [1.5, 2.5, 3.5] 1.5 3 [1.5, 2.5, 3.5] 1.5 4 [apple, zebra, banana] apple 5 [apple, zebra, banana] apple for (T item : list)
pass 1 of 1737T max = list.get(0);38for (T item1 : list[1, 2, 3, 4, 5]) {39 if (item.compareTo(max) > 0) {17 passes — pass 1 is the card above pass itemlist1 1 [1, 2, 3, 4, 5] 2 2 [1, 2, 3, 4, 5] 3 3 [1, 2, 3, 4, 5] 4 4 [1, 2, 3, 4, 5] 5 5 [1, 2, 3, 4, 5] 6 1.5 [1.5, 2.5, 3.5] 7 2.5 [1.5, 2.5, 3.5] 8 3.5 [1.5, 2.5, 3.5] 9 1.5 [1.5, 2.5, 3.5] ⋯ 6 more passes ⋯ 16 zebra [apple, zebra, banana] 17 banana [apple, zebra, banana] max ← 2
pass 1 of 1038for (T item : list) {39 if (item.compareTo(max1) > 0) {40 max→ 2 = item2;41 }All 10 passes — pass 1 is the card above pass itemmax1 2 1 → 2 2 3 2 → 3 3 4 3 → 4 4 5 4 → 5 5 2.5 1.5 → 2.5 6 3.5 2.5 → 3.5 7 2.5 1.5 → 2.5 8 3.5 2.5 → 3.5 9 zebra apple → zebra 10 zebra apple → zebra return max;
42 }43 return max5;44}System.out.println(" Max double: " + Finder.max(doubles));
47System.out.println(" Max int: " + Finder.max(ints));48System.out.println(" Max double: " + Finder.max(doubles[1.5, 2.5, 3.5]));return max;
42 }43 return max3.5;44}System.out.println(" Max double: " + Finder.max(doubles));
47System.out.println(" Max int: " + Finder.max(ints));48System.out.println(" Max double: " + Finder.max(doubles[1.5, 2.5, 3.5]));output Max double: 3.5return max;
42 }43 return max3.5;44}System.out.println(" Max double: " + Finder.max(doubles));
47System.out.println(" Max int: " + Finder.max(ints));48System.out.println(" Max double: " + Finder.max(doubles[1.5, 2.5, 3.5]));4950List<String> words = Arrays.asList("apple", "zebra", "banana");51System.out.println(" Max string: " + Finder.max(words[apple, zebra, banana]));output Max double: 3.5return max;
42 }43 return maxzebra;44}System.out.println(" Max string: " + Finder.max(words));
50List<String> words = Arrays.asList("apple", "zebra", "banana");51System.out.println(" Max string: " + Finder.max(words[apple, zebra, banana]));output Max string: zebrareturn max;
42 }43 return maxzebra;44}System.out.println(" Max string: " + Finder.max(words));
50List<String> words = Arrays.asList("apple", "zebra", "banana");51System.out.println(" Max string: " + Finder.max(words[apple, zebra, banana]));5253System.out.println("\nCopy numbers:");output Max string: zebra Copy numbers: Copy numbers:public static void copyNumbers( List<? extends Num…
55class Copier {56 public static void copyNumbers(57 List<? extends Number> source[1, 2, 3, 4, 5],58 List<Number> dest[]) {59 dest.clear();60 for (Number num : source) { // Read as Numberfor (Number num : source)
pass 1 of 559dest.clear();60for (Number num1 : source[1, 2, 3, 4, 5]) { // Read as Number61 dest.add(num1);62}All 5 passes — pass 1 is the card above pass num1 1 2 2 3 3 4 4 5 5 System.out.println(" Copied: " + result);
67Copier.copyNumbers(ints, result);68System.out.println(" Copied: " + result[1, 2, 3, 4, 5]);6970System.out.println("\nAverage:");output Copied: [1, 2, 3, 4, 5] Copied: [1, 2, 3, 4, 5] Average: Average:public static double average(List<? extends Number> numbers)
72class Stats {73 public static double average(List<? extends Number> numbers[1, 2, 3, 4, 5]) {74 if (numbers.isEmpty()) {75 return 0;76 }77 return sum(numbers[1, 2, 3, 4, 5]) / numbers.size();78 }return total;
8 }9 return total15.0;10}System.out.println(" Min: " + Stats.min(doubles));
98System.out.println(" Average: " + Stats.average(ints));99System.out.println(" Min: " + Stats.min(doubles[1.5, 2.5, 3.5]));minVal ← 1.5, min ← 1.5
pass 1 of 280public static Number min(List<? extends Number> numbers[1.5, 2.5, 3.5]) {81 if (numbers.isEmpty()) {82 return null;83 }84 85 double minVal→ 1.5 = numbers.get(0).doubleValue();86 Number min→ 1.5 = numbers.get(0);for (Number num : numbers)
pass 1 of 688for (Number num1.5 : numbers[1.5, 2.5, 3.5]) {89 if (num.doubleValue() < minVal) {All 6 passes — pass 1 is the card above pass num1 1.5 2 2.5 3 3.5 4 1.5 5 2.5 6 3.5 return min;
93 }94 return min1.5;95}System.out.println(" Min: " + Stats.min(doubles));
98System.out.println(" Average: " + Stats.average(ints));99System.out.println(" Min: " + Stats.min(doubles[1.5, 2.5, 3.5]));output Min: 1.5minVal ← 1.5, min ← 1.5
pass 2 of 280public static Number min(List<? extends Number> numbers[1.5, 2.5, 3.5]) {81 if (numbers.isEmpty()) {82 return null;83 }84 85 double minVal→ 1.5 = numbers.get(0).doubleValue();86 Number min→ 1.5 = numbers.get(0);return min;
93 }94 return min1.5;95}System.out.println(" Min: " + Stats.min(doubles));
98System.out.println(" Average: " + Stats.average(ints));99System.out.println(" Min: " + Stats.min(doubles[1.5, 2.5, 3.5]));100101System.out.println("\nPrint comparable:");output Min: 1.5 Print comparable: Print comparable:copy ← [5, 1, 9, 3, 7]
pass 1 of 2103class Printer {104 public static <T extends Comparable<T>> void printSorted(105 List<? extends T> list[5, 1, 9, 3, 7]) {106 List<T> copy→ [5, 1, 9, 3, 7] = new ArrayList<>(list);107 Collections.sort(copy→ [1, 3, 5, 7, 9]);108 System.out.print(" Sorted: ");109 for (T item : copy) {output Sorted:for (T item : copy)
pass 1 of 9108System.out.print(" Sorted: ");109for (T item1 : copy[1, 3, 5, 7, 9]) {110 System.out.print(item1 + " ");111}output1All 9 passes — pass 1 is the card above pass itemcopy1 1 [1, 3, 5, 7, 9] 2 3 [1, 3, 5, 7, 9] 3 5 [1, 3, 5, 7, 9] 4 7 [1, 3, 5, 7, 9] 5 9 [1, 3, 5, 7, 9] 6 ant [ant, bee, cat, dog] 7 bee [ant, bee, cat, dog] 8 cat [ant, bee, cat, dog] 9 dog [ant, bee, cat, dog] System.out.println();
111 }112 System.out.println();113}Printer.printSorted(Arrays.asList("dog", "cat", "ant", "bee"));
116Printer.printSorted(Arrays.asList(5, 1, 9, 3, 7));117Printer.printSorted(Arrays.asList("dog", "cat", "ant", "bee"));copy ← [dog, cat, ant, bee]
pass 2 of 2103class Printer {104 public static <T extends Comparable<T>> void printSorted(105 List<? extends T> list[dog, cat, ant, bee]) {106 List<T> copy→ [dog, cat, ant, bee] = new ArrayList<>(list);107 Collections.sort(copy→ [ant, bee, cat, dog]);108 System.out.print(" Sorted: ");109 for (T item : copy) {output Sorted:System.out.println();
111 }112 System.out.println();113}numList ← []
116 Printer.printSorted(Arrays.asList(5, 1, 9, 3, 7));117 Printer.printSorted(Arrays.asList("dog", "cat", "ant", "bee"));118 119 System.out.println("\nLimitations:");120 121 List<? extends Number> numList→ [] = new ArrayList<Integer>();122 // numList.add(1); // Compile error123 // numList.add(1.5); // Compile error124 // numList.add(new Integer(1)); // Compile error125 126 System.out.println(" Cannot add to List<? extends Number>");127 System.out.println(" Reason: Don't know if it's Integer, Double, etc.");128}output Limitations: Cannot add to List<? extends Number> Reason: Don't know if it's Integer, Double, etc.
List<? extends Number> - accepts List
upper bounded wildcard
`<? extends T>` - producer. Read as T, can't add (except null).
Lower bounded wildcard
Accept type or supertypes.
LowerBound.java
Replay: real traced execution (multi-file project)
import java.util.*;
public class LowerBound {
public static void addIntegers(List<? super Integer> list) {
list.add(1); // Can add Integer
list.add(2);
list.add(3);
System.out.println(" Added integers: " + list);
}
public static void main(String[] args) {
System.out.println("Lower bounded wildcard:\n");
List<Integer> intList = new ArrayList<>();
List<Number> numList = new ArrayList<>();
List<Object> objList = new ArrayList<>();
addIntegers(intList);
addIntegers(numList);
addIntegers(objList);
// <? super T> means "unknown type that is T or superclass"
// Can add T elements
// Can read as Object only (don't know exact type)
// PECS: Consumer Super - use when writing/consuming
System.out.println("\nAdd all:");
class Adder {
public static <T> void addAll(
List<? super T> dest,
List<? extends T> src) {
for (T item : src) {
dest.add(item); // Can add T to super T
}
}
}
List<Number> numbers = new ArrayList<>();
List<Integer> ints = Arrays.asList(10, 20, 30);
List<Double> doubles = Arrays.asList(1.5, 2.5);
Adder.addAll(numbers, ints);
Adder.addAll(numbers, doubles);
System.out.println(" Combined: " + numbers);
System.out.println("\nFill list:");
class Filler {
public static <T> void fill(List<? super T> list, T value, int count) {
for (int i = 0; i < count; i++) {
list.add(value);
}
}
}
List<Object> objects = new ArrayList<>();
int fillCount = 3;
Filler.fill(objects, "hello", fillCount);
Filler.fill(objects, 42, 2);
System.out.println(" Filled: " + objects);
System.out.println("\nCopy method:");
class Copier {
public static <T> void copy(
List<? super T> dest,
List<? extends T> src) {
dest.clear();
for (T item : src) {
dest.add(item);
}
}
}
List<String> source = Arrays.asList("a", "b", "c");
List<Object> destination = new ArrayList<>();
Copier.copy(destination, source);
System.out.println(" Copied: " + destination);
System.out.println("\nAppend:");
class Appender {
public static void appendIntegers(List<? super Integer> list) {
for (int i = 1; i <= 5; i++) {
list.add(i);
}
}
}
List<Number> nums = new ArrayList<>();
Appender.appendIntegers(nums);
System.out.println(" Numbers: " + nums);
List<Object> objs = new ArrayList<>();
Appender.appendIntegers(objs);
System.out.println(" Objects: " + objs);
System.out.println("\nReading limitations:");
List<? super Integer> superList = new ArrayList<Number>();
superList.add(10);
superList.add(20);
// Can only read as Object
Object first = superList.get(0); // Only Object
// Integer val = superList.get(0); // Compile error
System.out.println(" First (as Object): " + first);
System.out.println(" Can only read as Object from List<? super Integer>");
System.out.println("\nPECS example:");
class PecsDemo {
// Producer Extends - reading from source
// Consumer Super - writing to destination
public static <T> void transfer(
List<? super T> dest, // Consumer - can add T
List<? extends T> src) { // Producer - can read T
for (T item : src) {
dest.add(item);
}
}
}
List<Integer> intSource = Arrays.asList(1, 2, 3);
List<Number> numDest = new ArrayList<>();
PecsDemo.transfer(numDest, intSource);
System.out.println(" Transferred: " + numDest);
}
}
import java.util.*;
public class LowerBound {
public static void addIntegers(List<? super Integer> list) {
list.add(1); // Can add Integer
list.add(2);
list.add(3);
System.out.println(" Added integers: " + list);
}
public static void main(String[] args) {
System.out.println("Lower bounded wildcard:\n");
List<Integer> intList = new ArrayList<>();
List<Number> numList = new ArrayList<>();
List<Object> objList = new ArrayList<>();
addIntegers(intList);
addIntegers(numList);
addIntegers(objList);
// <? super T> means "unknown type that is T or superclass"
// Can add T elements
// Can read as Object only (don't know exact type)
// PECS: Consumer Super - use when writing/consuming
System.out.println("\nAdd all:");
class Adder {
public static <T> void addAll(
List<? super T> dest,
List<? extends T> src) {
for (T item : src) {
dest.add(item); // Can add T to super T
}
}
}
List<Number> numbers = new ArrayList<>();
List<Integer> ints = Arrays.asList(10, 20, 30);
List<Double> doubles = Arrays.asList(1.5, 2.5);
Adder.addAll(numbers, ints);
Adder.addAll(numbers, doubles);
System.out.println(" Combined: " + numbers);
System.out.println("\nFill list:");
class Filler {
public static <T> void fill(List<? super T> list, T value, int count) {
for (int i = 0; i < count; i++) {
list.add(value);
}
}
}
List<Object> objects = new ArrayList<>();
int fillCount = 1;
Filler.fill(objects, "hello", fillCount);
Filler.fill(objects, 42, 2);
System.out.println(" Filled: " + objects);
System.out.println("\nCopy method:");
class Copier {
public static <T> void copy(
List<? super T> dest,
List<? extends T> src) {
dest.clear();
for (T item : src) {
dest.add(item);
}
}
}
List<String> source = Arrays.asList("a", "b", "c");
List<Object> destination = new ArrayList<>();
Copier.copy(destination, source);
System.out.println(" Copied: " + destination);
System.out.println("\nAppend:");
class Appender {
public static void appendIntegers(List<? super Integer> list) {
for (int i = 1; i <= 5; i++) {
list.add(i);
}
}
}
List<Number> nums = new ArrayList<>();
Appender.appendIntegers(nums);
System.out.println(" Numbers: " + nums);
List<Object> objs = new ArrayList<>();
Appender.appendIntegers(objs);
System.out.println(" Objects: " + objs);
System.out.println("\nReading limitations:");
List<? super Integer> superList = new ArrayList<Number>();
superList.add(10);
superList.add(20);
// Can only read as Object
Object first = superList.get(0); // Only Object
// Integer val = superList.get(0); // Compile error
System.out.println(" First (as Object): " + first);
System.out.println(" Can only read as Object from List<? super Integer>");
System.out.println("\nPECS example:");
class PecsDemo {
// Producer Extends - reading from source
// Consumer Super - writing to destination
public static <T> void transfer(
List<? super T> dest, // Consumer - can add T
List<? extends T> src) { // Producer - can read T
for (T item : src) {
dest.add(item);
}
}
}
List<Integer> intSource = Arrays.asList(1, 2, 3);
List<Number> numDest = new ArrayList<>();
PecsDemo.transfer(numDest, intSource);
System.out.println(" Transferred: " + numDest);
}
}
import java.util.*;
public class LowerBound {
public static void addIntegers(List<? super Integer> list) {
list.add(1); // Can add Integer
list.add(2);
list.add(3);
System.out.println(" Added integers: " + list);
}
public static void main(String[] args) {
System.out.println("Lower bounded wildcard:\n");
List<Integer> intList = new ArrayList<>();
List<Number> numList = new ArrayList<>();
List<Object> objList = new ArrayList<>();
addIntegers(intList);
addIntegers(numList);
addIntegers(objList);
// <? super T> means "unknown type that is T or superclass"
// Can add T elements
// Can read as Object only (don't know exact type)
// PECS: Consumer Super - use when writing/consuming
System.out.println("\nAdd all:");
class Adder {
public static <T> void addAll(
List<? super T> dest,
List<? extends T> src) {
for (T item : src) {
dest.add(item); // Can add T to super T
}
}
}
List<Number> numbers = new ArrayList<>();
List<Integer> ints = Arrays.asList(10, 20, 30);
List<Double> doubles = Arrays.asList(1.5, 2.5);
Adder.addAll(numbers, ints);
Adder.addAll(numbers, doubles);
System.out.println(" Combined: " + numbers);
System.out.println("\nFill list:");
class Filler {
public static <T> void fill(List<? super T> list, T value, int count) {
for (int i = 0; i < count; i++) {
list.add(value);
}
}
}
List<Object> objects = new ArrayList<>();
int fillCount = 5;
Filler.fill(objects, "hello", fillCount);
Filler.fill(objects, 42, 2);
System.out.println(" Filled: " + objects);
System.out.println("\nCopy method:");
class Copier {
public static <T> void copy(
List<? super T> dest,
List<? extends T> src) {
dest.clear();
for (T item : src) {
dest.add(item);
}
}
}
List<String> source = Arrays.asList("a", "b", "c");
List<Object> destination = new ArrayList<>();
Copier.copy(destination, source);
System.out.println(" Copied: " + destination);
System.out.println("\nAppend:");
class Appender {
public static void appendIntegers(List<? super Integer> list) {
for (int i = 1; i <= 5; i++) {
list.add(i);
}
}
}
List<Number> nums = new ArrayList<>();
Appender.appendIntegers(nums);
System.out.println(" Numbers: " + nums);
List<Object> objs = new ArrayList<>();
Appender.appendIntegers(objs);
System.out.println(" Objects: " + objs);
System.out.println("\nReading limitations:");
List<? super Integer> superList = new ArrayList<Number>();
superList.add(10);
superList.add(20);
// Can only read as Object
Object first = superList.get(0); // Only Object
// Integer val = superList.get(0); // Compile error
System.out.println(" First (as Object): " + first);
System.out.println(" Can only read as Object from List<? super Integer>");
System.out.println("\nPECS example:");
class PecsDemo {
// Producer Extends - reading from source
// Consumer Super - writing to destination
public static <T> void transfer(
List<? super T> dest, // Consumer - can add T
List<? extends T> src) { // Producer - can read T
for (T item : src) {
dest.add(item);
}
}
}
List<Integer> intSource = Arrays.asList(1, 2, 3);
List<Number> numDest = new ArrayList<>();
PecsDemo.transfer(numDest, intSource);
System.out.println(" Transferred: " + numDest);
}
}
public static void main(String[] args)
11public static void main(String[] args) {12 System.out.println("Lower bounded wildcard:\n");outputLower bounded wildcard: Lower bounded wildcard:public static void addIntegers(List<? super Integer> list)
pass 1 of 33public class LowerBound {4 public static void addIntegers(List<? super Integer> list[]) {5 list.add(1); // Can add Integer6 list.add(2);7 list.add(3);8 System.out.println(" Added integers: " + list[1, 2, 3]);9 }output Added integers: [1, 2, 3]System.out.println(" Add all:");
27System.out.println("\nAdd all:");output Add all: Add all:public static <T> void addAll( List<? super T> des…
pass 1 of 229class Adder {30 public static <T> void addAll(31 List<? super T> dest[],32 List<? extends T> src[10, 20, 30]) {33 for (T item : src) {for (T item : src)
pass 1 of 532 List<? extends T> src) {33for (T item10 : src[10, 20, 30]) {34 dest.add(item10); // Can add T to super T35}All 5 passes — pass 1 is the card above pass itemsrcdest1 10 [10, 20, 30] — 2 20 [10, 20, 30] — 3 30 [10, 20, 30] [10, 20, 30] 4 1.5 [1.5, 2.5] — 5 2.5 [1.5, 2.5] — public static <T> void addAll( List<? super T> des…
pass 2 of 229class Adder {30 public static <T> void addAll(31 List<? super T> dest[10, 20, 30],32 List<? extends T> src[1.5, 2.5]) {33 for (T item : src) {System.out.println(" Combined: " + numbers);
46System.out.println(" Combined: " + numbers[10, 20, 30, 1.5, 2.5]);4748System.out.println("\nFill list:");output Combined: [10, 20, 30, 1.5, 2.5] Combined: [10, 20, 30, 1.5, 2.5] Fill list: Fill list:public static <T> void fill(List<? super T> list, T value, int count)
pass 1 of 250class Filler {51 public static <T> void fill(List<? super T> list[], T valuehello, int count3) {52 for (int i = 0; i < count; i++) {for (int i = 0; i < count; i++)
pass 1 of 551public static <T> void fill(List<? super T> list, T value, int count) {52 for (int i0 = 0; i < count3; i++) {53 list.add(valuehello);54 }All 5 passes — pass 1 is the card above pass icountvaluelist1 0 3 hello — 2 1 3 hello — 3 2 3 hello [hello, hello, hello] 4 0 2 42 — 5 1 2 42 — public static <T> void fill(List<? super T> list, T value, int count)
pass 2 of 250class Filler {51 public static <T> void fill(List<? super T> list[hello, hello, hello], T value42, int count2) {52 for (int i = 0; i < count; i++) {System.out.println(" Filled: " + objects);
63System.out.println(" Filled: " + objects[hello, hello, hello, 42, 42]);6465System.out.println("\nCopy method:");output Filled: [hello, hello, hello, 42, 42] Filled: [hello, hello, hello, 42, 42] Copy method: Copy method:public static <T> void copy( List<? super T> dest,…
67class Copier {68 public static <T> void copy(69 List<? super T> dest[],70 List<? extends T> src[a, b, c]) {71 dest.clear();72 for (T item : src) {for (T item : src)
pass 1 of 371dest.clear();72for (T itema : src[a, b, c]) {73 dest.add(itema);74}All 3 passes — pass 1 is the card above pass item1 a 2 b 3 c System.out.println(" Copied: " + destination);
81Copier.copy(destination, source);82System.out.println(" Copied: " + destination[a, b, c]);8384System.out.println("\nAppend:");output Copied: [a, b, c] Copied: [a, b, c] Append: Append:public static void appendIntegers(List<? super Integer> list)
pass 1 of 286class Appender {87 public static void appendIntegers(List<? super Integer> list[]) {88 for (int i = 1; i <= 5; i++) {for (int i = 1; i <= 5; i++)
pass 1 of 1087public static void appendIntegers(List<? super Integer> list) {88 for (int i1 = 1; i <= 5; i++) {89 list.add(i1);90 }All 10 passes — pass 1 is the card above pass i1 1 2 2 3 3 4 4 5 5 6 1 7 2 8 3 9 4 10 5 System.out.println(" Numbers: " + nums);
95Appender.appendIntegers(nums);96System.out.println(" Numbers: " + nums[1, 2, 3, 4, 5]);output Numbers: [1, 2, 3, 4, 5] Numbers: [1, 2, 3, 4, 5]public static void appendIntegers(List<? super Integer> list)
pass 2 of 286class Appender {87 public static void appendIntegers(List<? super Integer> list[]) {88 for (int i = 1; i <= 5; i++) {numDest ← []
99Appender.appendIntegers(objs);100System.out.println(" Objects: " + objs[1, 2, 3, 4, 5]);101102System.out.println("\nReading limitations:");103104List<? super Integer> superList = new ArrayList<Number>();105superList.add(10);106superList.add(20);107108// Can only read as Object109Object first = superList.get(0); // Only Object110// Integer val = superList.get(0); // Compile error111112System.out.println(" First (as Object): " + first10);113System.out.println(" Can only read as Object from List<? super Integer>");114115System.out.println("\nPECS example:");116117class PecsDemo {118 // Producer Extends - reading from source119 // Consumer Super - writing to destination120 public static <T> void transfer(121 List<? super T> dest, // Consumer - can add T122 List<? extends T> src) { // Producer - can read T123 for (T item : src) {124 dest.add(item);125 }126 }127}128129List<Integer> intSource = Arrays.asList(1, 2, 3);130List<Number> numDest→ [] = new ArrayList<>();131132PecsDemo.transfer(numDest[], intSource[1, 2, 3]);133System.out.println(" Transferred: " + numDest);output Objects: [1, 2, 3, 4, 5] Objects: [1, 2, 3, 4, 5] Reading limitations: Reading limitations: First (as Object): 10 First (as Object): 10 Can only read as Object from List<? super Integer> Can only read as Object from List<? super Integer> PECS example: PECS example:public static <T> void transfer( List<? super T> d…
119// Consumer Super - writing to destination120public static <T> void transfer(121 List<? super T> dest[], // Consumer - can add T122 List<? extends T> src[1, 2, 3]) { // Producer - can read T123 for (T item : src) {for (T item : src)
pass 1 of 3122 List<? extends T> src) { // Producer - can read T123for (T item1 : src[1, 2, 3]) {124 dest.add(item1);125}All 3 passes — pass 1 is the card above pass item1 1 2 2 3 3 numDest ← [1, 2, 3]
132 PecsDemo.transfer(numDest→ [1, 2, 3], intSource[1, 2, 3]);133 System.out.println(" Transferred: " + numDest[1, 2, 3]);134}output Transferred: [1, 2, 3]
public static void main(String[] args)
11public static void main(String[] args) {12 System.out.println("Lower bounded wildcard:\n");outputLower bounded wildcard: Lower bounded wildcard:public static void addIntegers(List<? super Integer> list)
pass 1 of 33public class LowerBound {4 public static void addIntegers(List<? super Integer> list[]) {5 list.add(1); // Can add Integer6 list.add(2);7 list.add(3);8 System.out.println(" Added integers: " + list[1, 2, 3]);9 }output Added integers: [1, 2, 3]System.out.println(" Add all:");
27System.out.println("\nAdd all:");output Add all: Add all:public static <T> void addAll( List<? super T> des…
pass 1 of 229class Adder {30 public static <T> void addAll(31 List<? super T> dest[],32 List<? extends T> src[10, 20, 30]) {33 for (T item : src) {for (T item : src)
pass 1 of 532 List<? extends T> src) {33for (T item10 : src[10, 20, 30]) {34 dest.add(item10); // Can add T to super T35}All 5 passes — pass 1 is the card above pass itemsrcdest1 10 [10, 20, 30] — 2 20 [10, 20, 30] — 3 30 [10, 20, 30] [10, 20, 30] 4 1.5 [1.5, 2.5] — 5 2.5 [1.5, 2.5] — public static <T> void addAll( List<? super T> des…
pass 2 of 229class Adder {30 public static <T> void addAll(31 List<? super T> dest[10, 20, 30],32 List<? extends T> src[1.5, 2.5]) {33 for (T item : src) {System.out.println(" Combined: " + numbers);
46System.out.println(" Combined: " + numbers[10, 20, 30, 1.5, 2.5]);4748System.out.println("\nFill list:");output Combined: [10, 20, 30, 1.5, 2.5] Combined: [10, 20, 30, 1.5, 2.5] Fill list: Fill list:public static <T> void fill(List<? super T> list, T value, int count)
pass 1 of 250class Filler {51 public static <T> void fill(List<? super T> list[], T valuehello, int count1) {52 for (int i = 0; i < count; i++) {for (int i = 0; i < count; i++)
pass 1 of 351public static <T> void fill(List<? super T> list, T value, int count) {52 for (int i0 = 0; i < count1; i++) {53 list.add(valuehello);54 }All 3 passes — pass 1 is the card above pass icountvaluelist1 0 1 hello [hello] 2 0 2 42 — 3 1 2 42 — public static <T> void fill(List<? super T> list, T value, int count)
pass 2 of 250class Filler {51 public static <T> void fill(List<? super T> list[hello], T value42, int count2) {52 for (int i = 0; i < count; i++) {System.out.println(" Filled: " + objects);
63System.out.println(" Filled: " + objects[hello, 42, 42]);6465System.out.println("\nCopy method:");output Filled: [hello, 42, 42] Filled: [hello, 42, 42] Copy method: Copy method:public static <T> void copy( List<? super T> dest,…
67class Copier {68 public static <T> void copy(69 List<? super T> dest[],70 List<? extends T> src[a, b, c]) {71 dest.clear();72 for (T item : src) {for (T item : src)
pass 1 of 371dest.clear();72for (T itema : src[a, b, c]) {73 dest.add(itema);74}All 3 passes — pass 1 is the card above pass item1 a 2 b 3 c System.out.println(" Copied: " + destination);
81Copier.copy(destination, source);82System.out.println(" Copied: " + destination[a, b, c]);8384System.out.println("\nAppend:");output Copied: [a, b, c] Copied: [a, b, c] Append: Append:public static void appendIntegers(List<? super Integer> list)
pass 1 of 286class Appender {87 public static void appendIntegers(List<? super Integer> list[]) {88 for (int i = 1; i <= 5; i++) {for (int i = 1; i <= 5; i++)
pass 1 of 1087public static void appendIntegers(List<? super Integer> list) {88 for (int i1 = 1; i <= 5; i++) {89 list.add(i1);90 }All 10 passes — pass 1 is the card above pass i1 1 2 2 3 3 4 4 5 5 6 1 7 2 8 3 9 4 10 5 System.out.println(" Numbers: " + nums);
95Appender.appendIntegers(nums);96System.out.println(" Numbers: " + nums[1, 2, 3, 4, 5]);output Numbers: [1, 2, 3, 4, 5] Numbers: [1, 2, 3, 4, 5]public static void appendIntegers(List<? super Integer> list)
pass 2 of 286class Appender {87 public static void appendIntegers(List<? super Integer> list[]) {88 for (int i = 1; i <= 5; i++) {numDest ← []
99Appender.appendIntegers(objs);100System.out.println(" Objects: " + objs[1, 2, 3, 4, 5]);101102System.out.println("\nReading limitations:");103104List<? super Integer> superList = new ArrayList<Number>();105superList.add(10);106superList.add(20);107108// Can only read as Object109Object first = superList.get(0); // Only Object110// Integer val = superList.get(0); // Compile error111112System.out.println(" First (as Object): " + first10);113System.out.println(" Can only read as Object from List<? super Integer>");114115System.out.println("\nPECS example:");116117class PecsDemo {118 // Producer Extends - reading from source119 // Consumer Super - writing to destination120 public static <T> void transfer(121 List<? super T> dest, // Consumer - can add T122 List<? extends T> src) { // Producer - can read T123 for (T item : src) {124 dest.add(item);125 }126 }127}128129List<Integer> intSource = Arrays.asList(1, 2, 3);130List<Number> numDest→ [] = new ArrayList<>();131132PecsDemo.transfer(numDest[], intSource[1, 2, 3]);133System.out.println(" Transferred: " + numDest);output Objects: [1, 2, 3, 4, 5] Objects: [1, 2, 3, 4, 5] Reading limitations: Reading limitations: First (as Object): 10 First (as Object): 10 Can only read as Object from List<? super Integer> Can only read as Object from List<? super Integer> PECS example: PECS example:public static <T> void transfer( List<? super T> d…
119// Consumer Super - writing to destination120public static <T> void transfer(121 List<? super T> dest[], // Consumer - can add T122 List<? extends T> src[1, 2, 3]) { // Producer - can read T123 for (T item : src) {for (T item : src)
pass 1 of 3122 List<? extends T> src) { // Producer - can read T123for (T item1 : src[1, 2, 3]) {124 dest.add(item1);125}All 3 passes — pass 1 is the card above pass item1 1 2 2 3 3 numDest ← [1, 2, 3]
132 PecsDemo.transfer(numDest→ [1, 2, 3], intSource[1, 2, 3]);133 System.out.println(" Transferred: " + numDest[1, 2, 3]);134}output Transferred: [1, 2, 3]
public static void main(String[] args)
11public static void main(String[] args) {12 System.out.println("Lower bounded wildcard:\n");outputLower bounded wildcard: Lower bounded wildcard:public static void addIntegers(List<? super Integer> list)
pass 1 of 33public class LowerBound {4 public static void addIntegers(List<? super Integer> list[]) {5 list.add(1); // Can add Integer6 list.add(2);7 list.add(3);8 System.out.println(" Added integers: " + list[1, 2, 3]);9 }output Added integers: [1, 2, 3]System.out.println(" Add all:");
27System.out.println("\nAdd all:");output Add all: Add all:public static <T> void addAll( List<? super T> des…
pass 1 of 229class Adder {30 public static <T> void addAll(31 List<? super T> dest[],32 List<? extends T> src[10, 20, 30]) {33 for (T item : src) {for (T item : src)
pass 1 of 532 List<? extends T> src) {33for (T item10 : src[10, 20, 30]) {34 dest.add(item10); // Can add T to super T35}All 5 passes — pass 1 is the card above pass itemsrcdest1 10 [10, 20, 30] — 2 20 [10, 20, 30] — 3 30 [10, 20, 30] [10, 20, 30] 4 1.5 [1.5, 2.5] — 5 2.5 [1.5, 2.5] — public static <T> void addAll( List<? super T> des…
pass 2 of 229class Adder {30 public static <T> void addAll(31 List<? super T> dest[10, 20, 30],32 List<? extends T> src[1.5, 2.5]) {33 for (T item : src) {System.out.println(" Combined: " + numbers);
46System.out.println(" Combined: " + numbers[10, 20, 30, 1.5, 2.5]);4748System.out.println("\nFill list:");output Combined: [10, 20, 30, 1.5, 2.5] Combined: [10, 20, 30, 1.5, 2.5] Fill list: Fill list:public static <T> void fill(List<? super T> list, T value, int count)
pass 1 of 250class Filler {51 public static <T> void fill(List<? super T> list[], T valuehello, int count5) {52 for (int i = 0; i < count; i++) {for (int i = 0; i < count; i++)
pass 1 of 751public static <T> void fill(List<? super T> list, T value, int count) {52 for (int i0 = 0; i < count5; i++) {53 list.add(valuehello);54 }All 7 passes — pass 1 is the card above pass icountvaluelist1 0 5 hello — 2 1 5 hello — 3 2 5 hello — 4 3 5 hello — 5 4 5 hello [hello, hello, hello, hello, hello] 6 0 2 42 — 7 1 2 42 — public static <T> void fill(List<? super T> list, T value, int count)
pass 2 of 250class Filler {51 public static <T> void fill(List<? super T> list[hello, hello, hello, hello, hello], T value42, int count2) {52 for (int i = 0; i < count; i++) {System.out.println(" Filled: " + objects);
63System.out.println(" Filled: " + objects[hello, hello, hello, hello, hello, 42, 42]);6465System.out.println("\nCopy method:");output Filled: [hello, hello, hello, hello, hello, 42, 42] Filled: [hello, hello, hello, hello, hello, 42, 42] Copy method: Copy method:public static <T> void copy( List<? super T> dest,…
67class Copier {68 public static <T> void copy(69 List<? super T> dest[],70 List<? extends T> src[a, b, c]) {71 dest.clear();72 for (T item : src) {for (T item : src)
pass 1 of 371dest.clear();72for (T itema : src[a, b, c]) {73 dest.add(itema);74}All 3 passes — pass 1 is the card above pass item1 a 2 b 3 c System.out.println(" Copied: " + destination);
81Copier.copy(destination, source);82System.out.println(" Copied: " + destination[a, b, c]);8384System.out.println("\nAppend:");output Copied: [a, b, c] Copied: [a, b, c] Append: Append:public static void appendIntegers(List<? super Integer> list)
pass 1 of 286class Appender {87 public static void appendIntegers(List<? super Integer> list[]) {88 for (int i = 1; i <= 5; i++) {for (int i = 1; i <= 5; i++)
pass 1 of 1087public static void appendIntegers(List<? super Integer> list) {88 for (int i1 = 1; i <= 5; i++) {89 list.add(i1);90 }All 10 passes — pass 1 is the card above pass i1 1 2 2 3 3 4 4 5 5 6 1 7 2 8 3 9 4 10 5 System.out.println(" Numbers: " + nums);
95Appender.appendIntegers(nums);96System.out.println(" Numbers: " + nums[1, 2, 3, 4, 5]);output Numbers: [1, 2, 3, 4, 5] Numbers: [1, 2, 3, 4, 5]public static void appendIntegers(List<? super Integer> list)
pass 2 of 286class Appender {87 public static void appendIntegers(List<? super Integer> list[]) {88 for (int i = 1; i <= 5; i++) {numDest ← []
99Appender.appendIntegers(objs);100System.out.println(" Objects: " + objs[1, 2, 3, 4, 5]);101102System.out.println("\nReading limitations:");103104List<? super Integer> superList = new ArrayList<Number>();105superList.add(10);106superList.add(20);107108// Can only read as Object109Object first = superList.get(0); // Only Object110// Integer val = superList.get(0); // Compile error111112System.out.println(" First (as Object): " + first10);113System.out.println(" Can only read as Object from List<? super Integer>");114115System.out.println("\nPECS example:");116117class PecsDemo {118 // Producer Extends - reading from source119 // Consumer Super - writing to destination120 public static <T> void transfer(121 List<? super T> dest, // Consumer - can add T122 List<? extends T> src) { // Producer - can read T123 for (T item : src) {124 dest.add(item);125 }126 }127}128129List<Integer> intSource = Arrays.asList(1, 2, 3);130List<Number> numDest→ [] = new ArrayList<>();131132PecsDemo.transfer(numDest[], intSource[1, 2, 3]);133System.out.println(" Transferred: " + numDest);output Objects: [1, 2, 3, 4, 5] Objects: [1, 2, 3, 4, 5] Reading limitations: Reading limitations: First (as Object): 10 First (as Object): 10 Can only read as Object from List<? super Integer> Can only read as Object from List<? super Integer> PECS example: PECS example:public static <T> void transfer( List<? super T> d…
119// Consumer Super - writing to destination120public static <T> void transfer(121 List<? super T> dest[], // Consumer - can add T122 List<? extends T> src[1, 2, 3]) { // Producer - can read T123 for (T item : src) {for (T item : src)
pass 1 of 3122 List<? extends T> src) { // Producer - can read T123for (T item1 : src[1, 2, 3]) {124 dest.add(item1);125}All 3 passes — pass 1 is the card above pass item1 1 2 2 3 3 numDest ← [1, 2, 3]
132 PecsDemo.transfer(numDest→ [1, 2, 3], intSource[1, 2, 3]);133 System.out.println(" Transferred: " + numDest[1, 2, 3]);134}output Transferred: [1, 2, 3]
List<? super Integer> - accepts List
lower bounded wildcard
`<? super T>` - consumer. Can add T, read only as Object.
PECS principle
Producer Extends, Consumer Super.
Pecs.java
Replay: real traced execution (multi-file project)
import java.util.*;
public class Pecs {
static class Stack<E> {
private List<E> elements = new ArrayList<>();
public void push(E item) {
elements.add(item);
}
public E pop() {
if (elements.isEmpty()) {
return null;
}
return elements.remove(elements.size() - 1);
}
// Producer - pushes items from src to this stack
public void pushAll(Iterable<? extends E> src) {
for (E item : src) { // Reading from producer
push(item);
}
}
// Consumer - pops items from this stack to dst
public void popAll(Collection<? super E> dst) {
while (!elements.isEmpty()) {
dst.add(pop()); // Writing to consumer
}
}
public int size() {
return elements.size();
}
}
public static void main(String[] args) {
System.out.println("PECS principle:\n");
Stack<Number> numberStack = new Stack<>();
// Producer Extends - can push from Integer list
List<Integer> ints = Arrays.asList(1, 2, 3);
numberStack.pushAll(ints);
System.out.println(" Pushed integers, size: " + numberStack.size());
// Consumer Super - can pop to Object list
List<Object> objects = new ArrayList<>();
numberStack.popAll(objects);
System.out.println(" Popped to objects: " + objects);
// PECS: Producer Extends, Consumer Super
// Producer (reading): use <? extends T>
// Consumer (writing): use <? super T>
// Maximizes flexibility while maintaining type safety
System.out.println("\nCollection utilities:");
class CollectionUtils {
// Producer - reading from source
public static <T> void copy(
List<? super T> dest, // Consumer - writing
List<? extends T> src) { // Producer - reading
dest.clear();
for (T item : src) {
dest.add(item);
}
}
// Producer - reading from multiple sources
public static <T> void addAll(
Collection<? super T> dest, // Consumer
Collection<? extends T>... sources) { // Producers
for (Collection<? extends T> src : sources) {
for (T item : src) {
dest.add(item);
}
}
}
}
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.5, 2.5);
List<Number> numberList = new ArrayList<>();
CollectionUtils.addAll(numberList, intList, doubleList);
System.out.println(" Combined: " + numberList);
System.out.println("\nFrequency counter:");
class Counter {
public static <T> int frequency(
Collection<? extends T> collection, // Producer
T target) {
int count = 0;
for (T item : collection) { // Reading
if (item != null && item.equals(target)) {
count++;
}
}
return count;
}
}
List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1, 2);
int frequencyTarget = 2;
System.out.println(" Frequency of " + frequencyTarget + ": " +
Counter.frequency(numbers, frequencyTarget));
System.out.println("\nMax with comparator:");
class MaxFinder {
public static <T> T max(
Collection<? extends T> coll, // Producer - reading
Comparator<? super T> comp) { // Consumer - comparing
if (coll.isEmpty()) {
return null;
}
Iterator<? extends T> it = coll.iterator();
T max = it.next();
while (it.hasNext()) {
T item = it.next();
if (comp.compare(item, max) > 0) {
max = item;
}
}
return max;
}
}
List<String> words = Arrays.asList("apple", "zoo", "banana");
String maxWord = MaxFinder.max(words, String::compareTo);
System.out.println(" Max word: " + maxWord);
System.out.println("\nFilter:");
interface Predicate<T> {
boolean test(T item);
}
class Filter {
public static <T> void removeIf(
Collection<? extends T> source, // Producer - reading
Collection<? super T> dest, // Consumer - writing
Predicate<? super T> filter) { // Consumer - testing
for (T item : source) {
if (!filter.test(item)) {
dest.add(item);
}
}
}
}
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Number> evens = new ArrayList<>();
Filter.removeIf(nums, evens, n -> n % 2 != 0); // Keep evens
System.out.println(" Even numbers: " + evens);
System.out.println("\nMap transformation:");
interface Function<T, R> {
R apply(T item);
}
class Mapper {
public static <T, R> void map(
Collection<? extends T> source, // Producer
Collection<? super R> dest, // Consumer
Function<? super T, ? extends R> mapper) {
for (T item : source) {
R result = mapper.apply(item);
dest.add(result);
}
}
}
List<String> strings = Arrays.asList("1", "2", "3");
List<Object> parsed = new ArrayList<>();
Mapper.map(strings, parsed, Integer::parseInt);
System.out.println(" Parsed: " + parsed);
}
}
import java.util.*;
public class Pecs {
static class Stack<E> {
private List<E> elements = new ArrayList<>();
public void push(E item) {
elements.add(item);
}
public E pop() {
if (elements.isEmpty()) {
return null;
}
return elements.remove(elements.size() - 1);
}
// Producer - pushes items from src to this stack
public void pushAll(Iterable<? extends E> src) {
for (E item : src) { // Reading from producer
push(item);
}
}
// Consumer - pops items from this stack to dst
public void popAll(Collection<? super E> dst) {
while (!elements.isEmpty()) {
dst.add(pop()); // Writing to consumer
}
}
public int size() {
return elements.size();
}
}
public static void main(String[] args) {
System.out.println("PECS principle:\n");
Stack<Number> numberStack = new Stack<>();
// Producer Extends - can push from Integer list
List<Integer> ints = Arrays.asList(1, 2, 3);
numberStack.pushAll(ints);
System.out.println(" Pushed integers, size: " + numberStack.size());
// Consumer Super - can pop to Object list
List<Object> objects = new ArrayList<>();
numberStack.popAll(objects);
System.out.println(" Popped to objects: " + objects);
// PECS: Producer Extends, Consumer Super
// Producer (reading): use <? extends T>
// Consumer (writing): use <? super T>
// Maximizes flexibility while maintaining type safety
System.out.println("\nCollection utilities:");
class CollectionUtils {
// Producer - reading from source
public static <T> void copy(
List<? super T> dest, // Consumer - writing
List<? extends T> src) { // Producer - reading
dest.clear();
for (T item : src) {
dest.add(item);
}
}
// Producer - reading from multiple sources
public static <T> void addAll(
Collection<? super T> dest, // Consumer
Collection<? extends T>... sources) { // Producers
for (Collection<? extends T> src : sources) {
for (T item : src) {
dest.add(item);
}
}
}
}
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.5, 2.5);
List<Number> numberList = new ArrayList<>();
CollectionUtils.addAll(numberList, intList, doubleList);
System.out.println(" Combined: " + numberList);
System.out.println("\nFrequency counter:");
class Counter {
public static <T> int frequency(
Collection<? extends T> collection, // Producer
T target) {
int count = 0;
for (T item : collection) { // Reading
if (item != null && item.equals(target)) {
count++;
}
}
return count;
}
}
List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1, 2);
int frequencyTarget = 1;
System.out.println(" Frequency of " + frequencyTarget + ": " +
Counter.frequency(numbers, frequencyTarget));
System.out.println("\nMax with comparator:");
class MaxFinder {
public static <T> T max(
Collection<? extends T> coll, // Producer - reading
Comparator<? super T> comp) { // Consumer - comparing
if (coll.isEmpty()) {
return null;
}
Iterator<? extends T> it = coll.iterator();
T max = it.next();
while (it.hasNext()) {
T item = it.next();
if (comp.compare(item, max) > 0) {
max = item;
}
}
return max;
}
}
List<String> words = Arrays.asList("apple", "zoo", "banana");
String maxWord = MaxFinder.max(words, String::compareTo);
System.out.println(" Max word: " + maxWord);
System.out.println("\nFilter:");
interface Predicate<T> {
boolean test(T item);
}
class Filter {
public static <T> void removeIf(
Collection<? extends T> source, // Producer - reading
Collection<? super T> dest, // Consumer - writing
Predicate<? super T> filter) { // Consumer - testing
for (T item : source) {
if (!filter.test(item)) {
dest.add(item);
}
}
}
}
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Number> evens = new ArrayList<>();
Filter.removeIf(nums, evens, n -> n % 2 != 0); // Keep evens
System.out.println(" Even numbers: " + evens);
System.out.println("\nMap transformation:");
interface Function<T, R> {
R apply(T item);
}
class Mapper {
public static <T, R> void map(
Collection<? extends T> source, // Producer
Collection<? super R> dest, // Consumer
Function<? super T, ? extends R> mapper) {
for (T item : source) {
R result = mapper.apply(item);
dest.add(result);
}
}
}
List<String> strings = Arrays.asList("1", "2", "3");
List<Object> parsed = new ArrayList<>();
Mapper.map(strings, parsed, Integer::parseInt);
System.out.println(" Parsed: " + parsed);
}
}
import java.util.*;
public class Pecs {
static class Stack<E> {
private List<E> elements = new ArrayList<>();
public void push(E item) {
elements.add(item);
}
public E pop() {
if (elements.isEmpty()) {
return null;
}
return elements.remove(elements.size() - 1);
}
// Producer - pushes items from src to this stack
public void pushAll(Iterable<? extends E> src) {
for (E item : src) { // Reading from producer
push(item);
}
}
// Consumer - pops items from this stack to dst
public void popAll(Collection<? super E> dst) {
while (!elements.isEmpty()) {
dst.add(pop()); // Writing to consumer
}
}
public int size() {
return elements.size();
}
}
public static void main(String[] args) {
System.out.println("PECS principle:\n");
Stack<Number> numberStack = new Stack<>();
// Producer Extends - can push from Integer list
List<Integer> ints = Arrays.asList(1, 2, 3);
numberStack.pushAll(ints);
System.out.println(" Pushed integers, size: " + numberStack.size());
// Consumer Super - can pop to Object list
List<Object> objects = new ArrayList<>();
numberStack.popAll(objects);
System.out.println(" Popped to objects: " + objects);
// PECS: Producer Extends, Consumer Super
// Producer (reading): use <? extends T>
// Consumer (writing): use <? super T>
// Maximizes flexibility while maintaining type safety
System.out.println("\nCollection utilities:");
class CollectionUtils {
// Producer - reading from source
public static <T> void copy(
List<? super T> dest, // Consumer - writing
List<? extends T> src) { // Producer - reading
dest.clear();
for (T item : src) {
dest.add(item);
}
}
// Producer - reading from multiple sources
public static <T> void addAll(
Collection<? super T> dest, // Consumer
Collection<? extends T>... sources) { // Producers
for (Collection<? extends T> src : sources) {
for (T item : src) {
dest.add(item);
}
}
}
}
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.5, 2.5);
List<Number> numberList = new ArrayList<>();
CollectionUtils.addAll(numberList, intList, doubleList);
System.out.println(" Combined: " + numberList);
System.out.println("\nFrequency counter:");
class Counter {
public static <T> int frequency(
Collection<? extends T> collection, // Producer
T target) {
int count = 0;
for (T item : collection) { // Reading
if (item != null && item.equals(target)) {
count++;
}
}
return count;
}
}
List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1, 2);
int frequencyTarget = 4;
System.out.println(" Frequency of " + frequencyTarget + ": " +
Counter.frequency(numbers, frequencyTarget));
System.out.println("\nMax with comparator:");
class MaxFinder {
public static <T> T max(
Collection<? extends T> coll, // Producer - reading
Comparator<? super T> comp) { // Consumer - comparing
if (coll.isEmpty()) {
return null;
}
Iterator<? extends T> it = coll.iterator();
T max = it.next();
while (it.hasNext()) {
T item = it.next();
if (comp.compare(item, max) > 0) {
max = item;
}
}
return max;
}
}
List<String> words = Arrays.asList("apple", "zoo", "banana");
String maxWord = MaxFinder.max(words, String::compareTo);
System.out.println(" Max word: " + maxWord);
System.out.println("\nFilter:");
interface Predicate<T> {
boolean test(T item);
}
class Filter {
public static <T> void removeIf(
Collection<? extends T> source, // Producer - reading
Collection<? super T> dest, // Consumer - writing
Predicate<? super T> filter) { // Consumer - testing
for (T item : source) {
if (!filter.test(item)) {
dest.add(item);
}
}
}
}
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Number> evens = new ArrayList<>();
Filter.removeIf(nums, evens, n -> n % 2 != 0); // Keep evens
System.out.println(" Even numbers: " + evens);
System.out.println("\nMap transformation:");
interface Function<T, R> {
R apply(T item);
}
class Mapper {
public static <T, R> void map(
Collection<? extends T> source, // Producer
Collection<? super R> dest, // Consumer
Function<? super T, ? extends R> mapper) {
for (T item : source) {
R result = mapper.apply(item);
dest.add(result);
}
}
}
List<String> strings = Arrays.asList("1", "2", "3");
List<Object> parsed = new ArrayList<>();
Mapper.map(strings, parsed, Integer::parseInt);
System.out.println(" Parsed: " + parsed);
}
}
public static void main(String[] args)
37public static void main(String[] args) {38 System.out.println("PECS principle:\n");outputPECS principle: PECS principle:public void pushAll(Iterable<? extends E> src)
18// Producer - pushes items from src to this stack19public void pushAll(Iterable<? extends E> src[1, 2, 3]) {20 for (E item : src) { // Reading from producerfor (E item : src)
pass 1 of 319public void pushAll(Iterable<? extends E> src) {20 for (E item1 : src[1, 2, 3]) { // Reading from producer21 push(item1);22 }All 3 passes — pass 1 is the card above pass item1 1 2 2 3 3 public void push(E item)
pass 1 of 37public void push(E item1) {8 elements.add(item1);9}All 3 passes — pass 1 is the card above pass item1 1 2 2 3 3 push(item);
20for (E item : src) { // Reading from producer21 push(item1);22}push(item);
20for (E item : src) { // Reading from producer21 push(item2);22}push(item);
20for (E item : src) { // Reading from producer21 push(item3);22}System.out.println(" Pushed integers, size: " + numberStack.size());
46System.out.println(" Pushed integers, size: " + numberStack.size());System.out.println(" Pushed integers, size: " + numberStack.size());
46System.out.println(" Pushed integers, size: " + numberStack.size());output Pushed integers, size: 3System.out.println(" Pushed integers, size: " + numberStack.size());
46System.out.println(" Pushed integers, size: " + numberStack.size());output Pushed integers, size: 3public void popAll(Collection<? super E> dst)
25// Consumer - pops items from this stack to dst26public void popAll(Collection<? super E> dst[]) {27 while (!elements.isEmpty()) {dst.add(pop()); // Writing to consumer
27while (!elements.isEmpty()) {28 dst.add(pop()); // Writing to consumer29}dst.add(pop()); // Writing to consumer
27while (!elements.isEmpty()) {28 dst.add(pop()); // Writing to consumer29}dst.add(pop()); // Writing to consumer
27while (!elements.isEmpty()) {28 dst.add(pop()); // Writing to consumer29}System.out.println(" Popped to objects: " + objects);
52System.out.println(" Popped to objects: " + objects[3, 2, 1]);5354// PECS: Producer Extends, Consumer Super55// Producer (reading): use <? extends T>56// Consumer (writing): use <? super T>57// Maximizes flexibility while maintaining type safety5859System.out.println("\nCollection utilities:");output Popped to objects: [3, 2, 1] Popped to objects: [3, 2, 1] Collection utilities: Collection utilities:public static <T> void addAll( Collection<? super …
72// Producer - reading from multiple sources73public static <T> void addAll(74 Collection<? super T> dest[], // Consumer75 Collection<? extends T>... sources) { // Producers76 for (Collection<? extends T> src : sources) {for (Collection<? extends T> src : sources)
pass 1 of 275 Collection<? extends T>... sources) { // Producers76for (Collection<? extends T> src[1, 2, 3] : sources) {77 for (T item : src) {for (T item : src)
pass 1 of 576for (Collection<? extends T> src : sources) {77 for (T item1 : src[1, 2, 3]) {78 dest.add(item1);79 }All 5 passes — pass 1 is the card above pass itemsrc1 1 [1, 2, 3] 2 2 [1, 2, 3] 3 3 [1, 2, 3] 4 1.5 [1.5, 2.5] 5 2.5 [1.5, 2.5] for (Collection<? extends T> src : sources)
pass 2 of 275 Collection<? extends T>... sources) { // Producers76for (Collection<? extends T> src[1.5, 2.5] : sources) {77 for (T item : src) {System.out.println(" Combined: " + numberList);
88CollectionUtils.addAll(numberList, intList, doubleList);89System.out.println(" Combined: " + numberList[1, 2, 3, 1.5, 2.5]);9091System.out.println("\nFrequency counter:");9293class Counter {94 public static <T> int frequency(95 Collection<? extends T> collection, // Producer96 T target) {97 int count = 0;98 for (T item : collection) { // Reading99 if (item != null && item.equals(target)) {100 count++;101 }102 }103 return count;104 }105}106107List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1, 2);108int frequencyTarget = 2; //@frequencyTarget=2, 1, 4109System.out.println(" Frequency of " + frequencyTarget2 + ": " +110 Counter.frequency(numbers[1, 2, 3, 2, 1, 2], frequencyTarget2));output Combined: [1, 2, 3, 1.5, 2.5] Combined: [1, 2, 3, 1.5, 2.5] Frequency counter: Frequency counter:count ← 0
pass 1 of 293class Counter {94 public static <T> int frequency(95 Collection<? extends T> collection[1, 2, 3, 2, 1, 2], // Producer96 T target2) {97 int count→ 0 = 0;98 for (T item : collection) { // Readingfor (T item : collection)
pass 1 of 1297int count = 0;98for (T item1 : collection[1, 2, 3, 2, 1, 2]) { // Reading99 if (item != null && item.equals(target)) {All 12 passes — pass 1 is the card above pass item1 1 2 2 3 3 4 2 5 1 6 2 7 1 8 2 9 3 10 2 11 1 12 2 count ← 1
pass 1 of 698for (T item : collection) { // Reading99 if (item2 != null && item.equals(target2)) {100 count→ 1++;101 }All 6 passes — pass 1 is the card above pass count1 0 → 1 2 1 → 2 3 2 → 3 4 0 → 1 5 1 → 2 6 2 → 3 return count;
102 }103 return count3;104}System.out.println(" Frequency of " + frequencyTarget + ": " +
108int frequencyTarget = 2; //@frequencyTarget=2, 1, 4109System.out.println(" Frequency of " + frequencyTarget2 + ": " +110 Counter.frequency(numbers[1, 2, 3, 2, 1, 2], frequencyTarget2));output Frequency of 2: 3count ← 0
pass 2 of 293class Counter {94 public static <T> int frequency(95 Collection<? extends T> collection[1, 2, 3, 2, 1, 2], // Producer96 T target2) {97 int count→ 0 = 0;98 for (T item : collection) { // Readingreturn count;
102 }103 return count3;104}System.out.println(" Frequency of " + frequencyTarget + ": " +
108int frequencyTarget = 2; //@frequencyTarget=2, 1, 4109System.out.println(" Frequency of " + frequencyTarget2 + ": " +110 Counter.frequency(numbers[1, 2, 3, 2, 1, 2], frequencyTarget2));111112System.out.println("\nMax with comparator:");113114class MaxFinder {115 public static <T> T max(116 Collection<? extends T> coll, // Producer - reading117 Comparator<? super T> comp) { // Consumer - comparing118 if (coll.isEmpty()) {119 return null;120 }121 122 Iterator<? extends T> it = coll.iterator();123 T max = it.next();124 125 while (it.hasNext()) {126 T item = it.next();127 if (comp.compare(item, max) > 0) {128 max = item;129 }130 }131 return max;132 }133}134135List<String> words = Arrays.asList("apple", "zoo", "banana");136String maxWord = MaxFinder.max(words[apple, zoo, banana], String::compareTo);137System.out.println(" Max word: " + maxWord);output Frequency of 2: 3 Max with comparator: Max with comparator:it ← ⟨Arrays$ArrayItr A⟩, max ← apple
114class MaxFinder {115 public static <T> T max(116 Collection<? extends T> coll[apple, zoo, banana], // Producer - reading117 Comparator<? super T> comp⟨Pecs lambda B⟩) { // Consumer - comparing118 if (coll.isEmpty()) {119 return null;120 }121 122 Iterator<? extends T> it→ ⟨Arrays$ArrayItr A⟩ = coll.iterator();123 T max→ apple = it.next();item ← zoo
pass 1 of 2125while (it.hasNext()) {126 T item→ zoo = it.next();127 if (comp.compare(item, max) > 0) {max ← zoo
126T item = it.next();127if (comp.compare(itemzoo, maxapple) > 0) {128 max→ zoo = itemzoo;129}item ← banana
pass 2 of 2125while (it.hasNext()) {126 T item→ banana = it.next();127 if (comp.compare(item, max) > 0) {return max;
130 }131 return maxzoo;132}maxWord ← zoo, evens ← []
135List<String> words = Arrays.asList("apple", "zoo", "banana");136String maxWord→ zoo = MaxFinder.max(words[apple, zoo, banana], String::compareTo);137System.out.println(" Max word: " + maxWordzoo);138139System.out.println("\nFilter:");140141interface Predicate<T> {142 boolean test(T item);143}144145class Filter {146 public static <T> void removeIf(147 Collection<? extends T> source, // Producer - reading148 Collection<? super T> dest, // Consumer - writing149 Predicate<? super T> filter) { // Consumer - testing150 for (T item : source) {151 if (!filter.test(item)) {152 dest.add(item);153 }154 }155 }156}157158List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);159List<Number> evens→ [] = new ArrayList<>();160161Filter.removeIf(nums[1, 2, 3, 4, 5, 6], evens[], n -> n % 2 != 0); // Keep evens162System.out.println(" Even numbers: " + evens);output Max word: zoo Filter:public static <T> void removeIf( Collection<? exte…
145class Filter {146 public static <T> void removeIf(147 Collection<? extends T> source[1, 2, 3, 4, 5, 6], // Producer - reading148 Collection<? super T> dest[], // Consumer - writing149 Predicate<? super T> filter⟨Pecs lambda C⟩) { // Consumer - testing150 for (T item : source) {for (T item : source)
pass 1 of 6149 Predicate<? super T> filter) { // Consumer - testing150for (T item1 : source[1, 2, 3, 4, 5, 6]) {151 if (!filter.test(item)) {All 6 passes — pass 1 is the card above pass item1 1 2 2 3 3 4 4 5 5 6 6 if (!filter.test(item))
pass 1 of 3150for (T item : source) {151 if (!filter.test(item2)) {152 dest.add(item2);153 }All 3 passes — pass 1 is the card above pass item1 2 2 4 3 6 evens ← [2, 4, 6], parsed ← []
161Filter.removeIf(nums[1, 2, 3, 4, 5, 6], evens→ [2, 4, 6], n -> n % 2 != 0); // Keep evens162System.out.println(" Even numbers: " + evens[2, 4, 6]);163164System.out.println("\nMap transformation:");165166interface Function<T, R> {167 R apply(T item);168}169170class Mapper {171 public static <T, R> void map(172 Collection<? extends T> source, // Producer173 Collection<? super R> dest, // Consumer174 Function<? super T, ? extends R> mapper) {175 for (T item : source) {176 R result = mapper.apply(item);177 dest.add(result);178 }179 }180}181182List<String> strings = Arrays.asList("1", "2", "3");183List<Object> parsed→ [] = new ArrayList<>();184185Mapper.map(strings[1, 2, 3], parsed[], Integer::parseInt);186System.out.println(" Parsed: " + parsed);output Even numbers: [2, 4, 6] Map transformation:public static <T, R> void map( Collection<? extend…
170class Mapper {171 public static <T, R> void map(172 Collection<? extends T> source[1, 2, 3], // Producer173 Collection<? super R> dest[], // Consumer174 Function<? super T, ? extends R> mapper⟨Pecs lambda D⟩) {175 for (T item : source) {result ← 1
pass 1 of 3174 Function<? super T, ? extends R> mapper) {175for (T item1 : source[1, 2, 3]) {176 R result→ 1 = mapper.apply(item1);177 dest.add(result1);178}All 3 passes — pass 1 is the card above pass itemresult1 1 1 2 2 2 3 3 3 parsed ← [1, 2, 3]
185 Mapper.map(strings[1, 2, 3], parsed→ [1, 2, 3], Integer::parseInt);186 System.out.println(" Parsed: " + parsed[1, 2, 3]);187}output Parsed: [1, 2, 3]
public static void main(String[] args)
37public static void main(String[] args) {38 System.out.println("PECS principle:\n");outputPECS principle: PECS principle:public void pushAll(Iterable<? extends E> src)
18// Producer - pushes items from src to this stack19public void pushAll(Iterable<? extends E> src[1, 2, 3]) {20 for (E item : src) { // Reading from producerfor (E item : src)
pass 1 of 319public void pushAll(Iterable<? extends E> src) {20 for (E item1 : src[1, 2, 3]) { // Reading from producer21 push(item1);22 }All 3 passes — pass 1 is the card above pass item1 1 2 2 3 3 public void push(E item)
pass 1 of 37public void push(E item1) {8 elements.add(item1);9}All 3 passes — pass 1 is the card above pass item1 1 2 2 3 3 push(item);
20for (E item : src) { // Reading from producer21 push(item1);22}push(item);
20for (E item : src) { // Reading from producer21 push(item2);22}push(item);
20for (E item : src) { // Reading from producer21 push(item3);22}System.out.println(" Pushed integers, size: " + numberStack.size());
46System.out.println(" Pushed integers, size: " + numberStack.size());System.out.println(" Pushed integers, size: " + numberStack.size());
46System.out.println(" Pushed integers, size: " + numberStack.size());output Pushed integers, size: 3System.out.println(" Pushed integers, size: " + numberStack.size());
46System.out.println(" Pushed integers, size: " + numberStack.size());output Pushed integers, size: 3public void popAll(Collection<? super E> dst)
25// Consumer - pops items from this stack to dst26public void popAll(Collection<? super E> dst[]) {27 while (!elements.isEmpty()) {dst.add(pop()); // Writing to consumer
27while (!elements.isEmpty()) {28 dst.add(pop()); // Writing to consumer29}dst.add(pop()); // Writing to consumer
27while (!elements.isEmpty()) {28 dst.add(pop()); // Writing to consumer29}dst.add(pop()); // Writing to consumer
27while (!elements.isEmpty()) {28 dst.add(pop()); // Writing to consumer29}System.out.println(" Popped to objects: " + objects);
52System.out.println(" Popped to objects: " + objects[3, 2, 1]);5354// PECS: Producer Extends, Consumer Super55// Producer (reading): use <? extends T>56// Consumer (writing): use <? super T>57// Maximizes flexibility while maintaining type safety5859System.out.println("\nCollection utilities:");output Popped to objects: [3, 2, 1] Popped to objects: [3, 2, 1] Collection utilities: Collection utilities:public static <T> void addAll( Collection<? super …
72// Producer - reading from multiple sources73public static <T> void addAll(74 Collection<? super T> dest[], // Consumer75 Collection<? extends T>... sources) { // Producers76 for (Collection<? extends T> src : sources) {for (Collection<? extends T> src : sources)
pass 1 of 275 Collection<? extends T>... sources) { // Producers76for (Collection<? extends T> src[1, 2, 3] : sources) {77 for (T item : src) {for (T item : src)
pass 1 of 576for (Collection<? extends T> src : sources) {77 for (T item1 : src[1, 2, 3]) {78 dest.add(item1);79 }All 5 passes — pass 1 is the card above pass itemsrc1 1 [1, 2, 3] 2 2 [1, 2, 3] 3 3 [1, 2, 3] 4 1.5 [1.5, 2.5] 5 2.5 [1.5, 2.5] for (Collection<? extends T> src : sources)
pass 2 of 275 Collection<? extends T>... sources) { // Producers76for (Collection<? extends T> src[1.5, 2.5] : sources) {77 for (T item : src) {System.out.println(" Combined: " + numberList);
88CollectionUtils.addAll(numberList, intList, doubleList);89System.out.println(" Combined: " + numberList[1, 2, 3, 1.5, 2.5]);9091System.out.println("\nFrequency counter:");9293class Counter {94 public static <T> int frequency(95 Collection<? extends T> collection, // Producer96 T target) {97 int count = 0;98 for (T item : collection) { // Reading99 if (item != null && item.equals(target)) {100 count++;101 }102 }103 return count;104 }105}106107List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1, 2);108int frequencyTarget = 1;109System.out.println(" Frequency of " + frequencyTarget1 + ": " +110 Counter.frequency(numbers[1, 2, 3, 2, 1, 2], frequencyTarget1));output Combined: [1, 2, 3, 1.5, 2.5] Combined: [1, 2, 3, 1.5, 2.5] Frequency counter: Frequency counter:count ← 0
pass 1 of 293class Counter {94 public static <T> int frequency(95 Collection<? extends T> collection[1, 2, 3, 2, 1, 2], // Producer96 T target1) {97 int count→ 0 = 0;98 for (T item : collection) { // Readingfor (T item : collection)
pass 1 of 1297int count = 0;98for (T item1 : collection[1, 2, 3, 2, 1, 2]) { // Reading99 if (item != null && item.equals(target)) {All 12 passes — pass 1 is the card above pass item1 1 2 2 3 3 4 2 5 1 6 2 7 1 8 2 9 3 10 2 11 1 12 2 count ← 1
pass 1 of 498for (T item : collection) { // Reading99 if (item1 != null && item.equals(target1)) {100 count→ 1++;101 }All 4 passes — pass 1 is the card above pass count1 0 → 1 2 1 → 2 3 0 → 1 4 1 → 2 return count;
102 }103 return count2;104}System.out.println(" Frequency of " + frequencyTarget + ": " +
108int frequencyTarget = 1;109System.out.println(" Frequency of " + frequencyTarget1 + ": " +110 Counter.frequency(numbers[1, 2, 3, 2, 1, 2], frequencyTarget1));output Frequency of 1: 2count ← 0
pass 2 of 293class Counter {94 public static <T> int frequency(95 Collection<? extends T> collection[1, 2, 3, 2, 1, 2], // Producer96 T target1) {97 int count→ 0 = 0;98 for (T item : collection) { // Readingreturn count;
102 }103 return count2;104}System.out.println(" Frequency of " + frequencyTarget + ": " +
108int frequencyTarget = 1;109System.out.println(" Frequency of " + frequencyTarget1 + ": " +110 Counter.frequency(numbers[1, 2, 3, 2, 1, 2], frequencyTarget1));111112System.out.println("\nMax with comparator:");113114class MaxFinder {115 public static <T> T max(116 Collection<? extends T> coll, // Producer - reading117 Comparator<? super T> comp) { // Consumer - comparing118 if (coll.isEmpty()) {119 return null;120 }121 122 Iterator<? extends T> it = coll.iterator();123 T max = it.next();124 125 while (it.hasNext()) {126 T item = it.next();127 if (comp.compare(item, max) > 0) {128 max = item;129 }130 }131 return max;132 }133}134135List<String> words = Arrays.asList("apple", "zoo", "banana");136String maxWord = MaxFinder.max(words[apple, zoo, banana], String::compareTo);137System.out.println(" Max word: " + maxWord);output Frequency of 1: 2 Max with comparator: Max with comparator:it ← ⟨Arrays$ArrayItr A⟩, max ← apple
114class MaxFinder {115 public static <T> T max(116 Collection<? extends T> coll[apple, zoo, banana], // Producer - reading117 Comparator<? super T> comp⟨Pecs lambda B⟩) { // Consumer - comparing118 if (coll.isEmpty()) {119 return null;120 }121 122 Iterator<? extends T> it→ ⟨Arrays$ArrayItr A⟩ = coll.iterator();123 T max→ apple = it.next();item ← zoo
pass 1 of 2125while (it.hasNext()) {126 T item→ zoo = it.next();127 if (comp.compare(item, max) > 0) {max ← zoo
126T item = it.next();127if (comp.compare(itemzoo, maxapple) > 0) {128 max→ zoo = itemzoo;129}item ← banana
pass 2 of 2125while (it.hasNext()) {126 T item→ banana = it.next();127 if (comp.compare(item, max) > 0) {return max;
130 }131 return maxzoo;132}maxWord ← zoo, evens ← []
135List<String> words = Arrays.asList("apple", "zoo", "banana");136String maxWord→ zoo = MaxFinder.max(words[apple, zoo, banana], String::compareTo);137System.out.println(" Max word: " + maxWordzoo);138139System.out.println("\nFilter:");140141interface Predicate<T> {142 boolean test(T item);143}144145class Filter {146 public static <T> void removeIf(147 Collection<? extends T> source, // Producer - reading148 Collection<? super T> dest, // Consumer - writing149 Predicate<? super T> filter) { // Consumer - testing150 for (T item : source) {151 if (!filter.test(item)) {152 dest.add(item);153 }154 }155 }156}157158List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);159List<Number> evens→ [] = new ArrayList<>();160161Filter.removeIf(nums[1, 2, 3, 4, 5, 6], evens[], n -> n % 2 != 0); // Keep evens162System.out.println(" Even numbers: " + evens);output Max word: zoo Filter:public static <T> void removeIf( Collection<? exte…
145class Filter {146 public static <T> void removeIf(147 Collection<? extends T> source[1, 2, 3, 4, 5, 6], // Producer - reading148 Collection<? super T> dest[], // Consumer - writing149 Predicate<? super T> filter⟨Pecs lambda C⟩) { // Consumer - testing150 for (T item : source) {for (T item : source)
pass 1 of 6149 Predicate<? super T> filter) { // Consumer - testing150for (T item1 : source[1, 2, 3, 4, 5, 6]) {151 if (!filter.test(item)) {All 6 passes — pass 1 is the card above pass item1 1 2 2 3 3 4 4 5 5 6 6 if (!filter.test(item))
pass 1 of 3150for (T item : source) {151 if (!filter.test(item2)) {152 dest.add(item2);153 }All 3 passes — pass 1 is the card above pass item1 2 2 4 3 6 evens ← [2, 4, 6], parsed ← []
161Filter.removeIf(nums[1, 2, 3, 4, 5, 6], evens→ [2, 4, 6], n -> n % 2 != 0); // Keep evens162System.out.println(" Even numbers: " + evens[2, 4, 6]);163164System.out.println("\nMap transformation:");165166interface Function<T, R> {167 R apply(T item);168}169170class Mapper {171 public static <T, R> void map(172 Collection<? extends T> source, // Producer173 Collection<? super R> dest, // Consumer174 Function<? super T, ? extends R> mapper) {175 for (T item : source) {176 R result = mapper.apply(item);177 dest.add(result);178 }179 }180}181182List<String> strings = Arrays.asList("1", "2", "3");183List<Object> parsed→ [] = new ArrayList<>();184185Mapper.map(strings[1, 2, 3], parsed[], Integer::parseInt);186System.out.println(" Parsed: " + parsed);output Even numbers: [2, 4, 6] Map transformation:public static <T, R> void map( Collection<? extend…
170class Mapper {171 public static <T, R> void map(172 Collection<? extends T> source[1, 2, 3], // Producer173 Collection<? super R> dest[], // Consumer174 Function<? super T, ? extends R> mapper⟨Pecs lambda D⟩) {175 for (T item : source) {result ← 1
pass 1 of 3174 Function<? super T, ? extends R> mapper) {175for (T item1 : source[1, 2, 3]) {176 R result→ 1 = mapper.apply(item1);177 dest.add(result1);178}All 3 passes — pass 1 is the card above pass itemresult1 1 1 2 2 2 3 3 3 parsed ← [1, 2, 3]
185 Mapper.map(strings[1, 2, 3], parsed→ [1, 2, 3], Integer::parseInt);186 System.out.println(" Parsed: " + parsed[1, 2, 3]);187}output Parsed: [1, 2, 3]
public static void main(String[] args)
37public static void main(String[] args) {38 System.out.println("PECS principle:\n");outputPECS principle: PECS principle:public void pushAll(Iterable<? extends E> src)
18// Producer - pushes items from src to this stack19public void pushAll(Iterable<? extends E> src[1, 2, 3]) {20 for (E item : src) { // Reading from producerfor (E item : src)
pass 1 of 319public void pushAll(Iterable<? extends E> src) {20 for (E item1 : src[1, 2, 3]) { // Reading from producer21 push(item1);22 }All 3 passes — pass 1 is the card above pass item1 1 2 2 3 3 public void push(E item)
pass 1 of 37public void push(E item1) {8 elements.add(item1);9}All 3 passes — pass 1 is the card above pass item1 1 2 2 3 3 push(item);
20for (E item : src) { // Reading from producer21 push(item1);22}push(item);
20for (E item : src) { // Reading from producer21 push(item2);22}push(item);
20for (E item : src) { // Reading from producer21 push(item3);22}System.out.println(" Pushed integers, size: " + numberStack.size());
46System.out.println(" Pushed integers, size: " + numberStack.size());System.out.println(" Pushed integers, size: " + numberStack.size());
46System.out.println(" Pushed integers, size: " + numberStack.size());output Pushed integers, size: 3System.out.println(" Pushed integers, size: " + numberStack.size());
46System.out.println(" Pushed integers, size: " + numberStack.size());output Pushed integers, size: 3public void popAll(Collection<? super E> dst)
25// Consumer - pops items from this stack to dst26public void popAll(Collection<? super E> dst[]) {27 while (!elements.isEmpty()) {dst.add(pop()); // Writing to consumer
27while (!elements.isEmpty()) {28 dst.add(pop()); // Writing to consumer29}dst.add(pop()); // Writing to consumer
27while (!elements.isEmpty()) {28 dst.add(pop()); // Writing to consumer29}dst.add(pop()); // Writing to consumer
27while (!elements.isEmpty()) {28 dst.add(pop()); // Writing to consumer29}System.out.println(" Popped to objects: " + objects);
52System.out.println(" Popped to objects: " + objects[3, 2, 1]);5354// PECS: Producer Extends, Consumer Super55// Producer (reading): use <? extends T>56// Consumer (writing): use <? super T>57// Maximizes flexibility while maintaining type safety5859System.out.println("\nCollection utilities:");output Popped to objects: [3, 2, 1] Popped to objects: [3, 2, 1] Collection utilities: Collection utilities:public static <T> void addAll( Collection<? super …
72// Producer - reading from multiple sources73public static <T> void addAll(74 Collection<? super T> dest[], // Consumer75 Collection<? extends T>... sources) { // Producers76 for (Collection<? extends T> src : sources) {for (Collection<? extends T> src : sources)
pass 1 of 275 Collection<? extends T>... sources) { // Producers76for (Collection<? extends T> src[1, 2, 3] : sources) {77 for (T item : src) {for (T item : src)
pass 1 of 576for (Collection<? extends T> src : sources) {77 for (T item1 : src[1, 2, 3]) {78 dest.add(item1);79 }All 5 passes — pass 1 is the card above pass itemsrc1 1 [1, 2, 3] 2 2 [1, 2, 3] 3 3 [1, 2, 3] 4 1.5 [1.5, 2.5] 5 2.5 [1.5, 2.5] for (Collection<? extends T> src : sources)
pass 2 of 275 Collection<? extends T>... sources) { // Producers76for (Collection<? extends T> src[1.5, 2.5] : sources) {77 for (T item : src) {System.out.println(" Combined: " + numberList);
88CollectionUtils.addAll(numberList, intList, doubleList);89System.out.println(" Combined: " + numberList[1, 2, 3, 1.5, 2.5]);9091System.out.println("\nFrequency counter:");9293class Counter {94 public static <T> int frequency(95 Collection<? extends T> collection, // Producer96 T target) {97 int count = 0;98 for (T item : collection) { // Reading99 if (item != null && item.equals(target)) {100 count++;101 }102 }103 return count;104 }105}106107List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1, 2);108int frequencyTarget = 4;109System.out.println(" Frequency of " + frequencyTarget4 + ": " +110 Counter.frequency(numbers[1, 2, 3, 2, 1, 2], frequencyTarget4));output Combined: [1, 2, 3, 1.5, 2.5] Combined: [1, 2, 3, 1.5, 2.5] Frequency counter: Frequency counter:count ← 0
pass 1 of 293class Counter {94 public static <T> int frequency(95 Collection<? extends T> collection[1, 2, 3, 2, 1, 2], // Producer96 T target4) {97 int count→ 0 = 0;98 for (T item : collection) { // Readingfor (T item : collection)
pass 1 of 1297int count = 0;98for (T item1 : collection[1, 2, 3, 2, 1, 2]) { // Reading99 if (item != null && item.equals(target)) {All 12 passes — pass 1 is the card above pass item1 1 2 2 3 3 4 2 5 1 6 2 7 1 8 2 9 3 10 2 11 1 12 2 return count;
102 }103 return count0;104}System.out.println(" Frequency of " + frequencyTarget + ": " +
108int frequencyTarget = 4;109System.out.println(" Frequency of " + frequencyTarget4 + ": " +110 Counter.frequency(numbers[1, 2, 3, 2, 1, 2], frequencyTarget4));output Frequency of 4: 0count ← 0
pass 2 of 293class Counter {94 public static <T> int frequency(95 Collection<? extends T> collection[1, 2, 3, 2, 1, 2], // Producer96 T target4) {97 int count→ 0 = 0;98 for (T item : collection) { // Readingreturn count;
102 }103 return count0;104}System.out.println(" Frequency of " + frequencyTarget + ": " +
108int frequencyTarget = 4;109System.out.println(" Frequency of " + frequencyTarget4 + ": " +110 Counter.frequency(numbers[1, 2, 3, 2, 1, 2], frequencyTarget4));111112System.out.println("\nMax with comparator:");113114class MaxFinder {115 public static <T> T max(116 Collection<? extends T> coll, // Producer - reading117 Comparator<? super T> comp) { // Consumer - comparing118 if (coll.isEmpty()) {119 return null;120 }121 122 Iterator<? extends T> it = coll.iterator();123 T max = it.next();124 125 while (it.hasNext()) {126 T item = it.next();127 if (comp.compare(item, max) > 0) {128 max = item;129 }130 }131 return max;132 }133}134135List<String> words = Arrays.asList("apple", "zoo", "banana");136String maxWord = MaxFinder.max(words[apple, zoo, banana], String::compareTo);137System.out.println(" Max word: " + maxWord);output Frequency of 4: 0 Max with comparator: Max with comparator:it ← ⟨Arrays$ArrayItr A⟩, max ← apple
114class MaxFinder {115 public static <T> T max(116 Collection<? extends T> coll[apple, zoo, banana], // Producer - reading117 Comparator<? super T> comp⟨Pecs lambda B⟩) { // Consumer - comparing118 if (coll.isEmpty()) {119 return null;120 }121 122 Iterator<? extends T> it→ ⟨Arrays$ArrayItr A⟩ = coll.iterator();123 T max→ apple = it.next();item ← zoo
pass 1 of 2125while (it.hasNext()) {126 T item→ zoo = it.next();127 if (comp.compare(item, max) > 0) {max ← zoo
126T item = it.next();127if (comp.compare(itemzoo, maxapple) > 0) {128 max→ zoo = itemzoo;129}item ← banana
pass 2 of 2125while (it.hasNext()) {126 T item→ banana = it.next();127 if (comp.compare(item, max) > 0) {return max;
130 }131 return maxzoo;132}maxWord ← zoo, evens ← []
135List<String> words = Arrays.asList("apple", "zoo", "banana");136String maxWord→ zoo = MaxFinder.max(words[apple, zoo, banana], String::compareTo);137System.out.println(" Max word: " + maxWordzoo);138139System.out.println("\nFilter:");140141interface Predicate<T> {142 boolean test(T item);143}144145class Filter {146 public static <T> void removeIf(147 Collection<? extends T> source, // Producer - reading148 Collection<? super T> dest, // Consumer - writing149 Predicate<? super T> filter) { // Consumer - testing150 for (T item : source) {151 if (!filter.test(item)) {152 dest.add(item);153 }154 }155 }156}157158List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);159List<Number> evens→ [] = new ArrayList<>();160161Filter.removeIf(nums[1, 2, 3, 4, 5, 6], evens[], n -> n % 2 != 0); // Keep evens162System.out.println(" Even numbers: " + evens);output Max word: zoo Filter:public static <T> void removeIf( Collection<? exte…
145class Filter {146 public static <T> void removeIf(147 Collection<? extends T> source[1, 2, 3, 4, 5, 6], // Producer - reading148 Collection<? super T> dest[], // Consumer - writing149 Predicate<? super T> filter⟨Pecs lambda C⟩) { // Consumer - testing150 for (T item : source) {for (T item : source)
pass 1 of 6149 Predicate<? super T> filter) { // Consumer - testing150for (T item1 : source[1, 2, 3, 4, 5, 6]) {151 if (!filter.test(item)) {All 6 passes — pass 1 is the card above pass item1 1 2 2 3 3 4 4 5 5 6 6 if (!filter.test(item))
pass 1 of 3150for (T item : source) {151 if (!filter.test(item2)) {152 dest.add(item2);153 }All 3 passes — pass 1 is the card above pass item1 2 2 4 3 6 evens ← [2, 4, 6], parsed ← []
161Filter.removeIf(nums[1, 2, 3, 4, 5, 6], evens→ [2, 4, 6], n -> n % 2 != 0); // Keep evens162System.out.println(" Even numbers: " + evens[2, 4, 6]);163164System.out.println("\nMap transformation:");165166interface Function<T, R> {167 R apply(T item);168}169170class Mapper {171 public static <T, R> void map(172 Collection<? extends T> source, // Producer173 Collection<? super R> dest, // Consumer174 Function<? super T, ? extends R> mapper) {175 for (T item : source) {176 R result = mapper.apply(item);177 dest.add(result);178 }179 }180}181182List<String> strings = Arrays.asList("1", "2", "3");183List<Object> parsed→ [] = new ArrayList<>();184185Mapper.map(strings[1, 2, 3], parsed[], Integer::parseInt);186System.out.println(" Parsed: " + parsed);output Even numbers: [2, 4, 6] Map transformation:public static <T, R> void map( Collection<? extend…
170class Mapper {171 public static <T, R> void map(172 Collection<? extends T> source[1, 2, 3], // Producer173 Collection<? super R> dest[], // Consumer174 Function<? super T, ? extends R> mapper⟨Pecs lambda D⟩) {175 for (T item : source) {result ← 1
pass 1 of 3174 Function<? super T, ? extends R> mapper) {175for (T item1 : source[1, 2, 3]) {176 R result→ 1 = mapper.apply(item1);177 dest.add(result1);178}All 3 passes — pass 1 is the card above pass itemresult1 1 1 2 2 2 3 3 3 parsed ← [1, 2, 3]
185 Mapper.map(strings[1, 2, 3], parsed→ [1, 2, 3], Integer::parseInt);186 System.out.println(" Parsed: " + parsed[1, 2, 3]);187}output Parsed: [1, 2, 3]
Read from ? extends. Write to ? super. Copy: src extends, dest super.
PECS
Producer Extends, Consumer Super. Guides wildcard choice for read vs write.
Wildcard capture
Convert wildcard to concrete type.
Capture.java
Replay: real traced execution (multi-file project)
import java.util.*;
public class Capture {
public static void reverse(List<?> list) {
reverseHelper(list); // Capture wildcard
}
private static <T> void reverseHelper(List<T> list) {
// Now T is a concrete captured type
int size = list.size();
for (int i = 0; i < size / 2; i++) {
T temp = list.get(i);
list.set(i, list.get(size - 1 - i));
list.set(size - 1 - i, temp);
}
}
public static void main(String[] args) {
System.out.println("Wildcard capture:\n");
List<Integer> ints = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
System.out.println(" Before: " + ints);
reverse(ints);
System.out.println(" After: " + ints);
List<String> strs = new ArrayList<>(Arrays.asList("a", "b", "c"));
System.out.println(" Before: " + strs);
reverse(strs);
System.out.println(" After: " + strs);
// Cannot manipulate elements in List<?> directly
// Use helper method with <T> to "capture" the type
// Helper method sees concrete type T
// Enables operations that need consistent type
System.out.println("\nSwap elements:");
class Swapper {
public static void swap(List<?> list, int i, int j) {
swapHelper(list, i, j);
}
private static <T> void swapHelper(List<T> list, int i, int j) {
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
List<Integer> numbers = new ArrayList<>(Arrays.asList(10, 20, 30, 40));
System.out.println(" Before: " + numbers);
Swapper.swap(numbers, 0, 3);
System.out.println(" After: " + numbers);
System.out.println("\nRotate list:");
class Rotator {
public static void rotate(List<?> list, int distance) {
rotateHelper(list, distance);
}
private static <T> void rotateHelper(List<T> list, int distance) {
int size = list.size();
if (size == 0) return;
distance = distance % size;
if (distance < 0) distance += size;
for (int i = 0; i < distance; i++) {
T last = list.remove(size - 1);
list.add(0, last);
}
}
}
List<String> words = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
System.out.println(" Before: " + words);
int rotateDistance = 2;
Rotator.rotate(words, rotateDistance);
System.out.println(" After: " + words);
System.out.println("\nShuffle:");
class Shuffler {
public static void shuffle(List<?> list) {
shuffleHelper(list);
}
private static <T> void shuffleHelper(List<T> list) {
Random random = new Random(42);
for (int i = list.size() - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
}
List<Integer> deck = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
System.out.println(" Before: " + deck);
Shuffler.shuffle(deck);
System.out.println(" After: " + deck);
System.out.println("\nFill with default:");
class Filler {
public static void fillWithDefault(List<?> list) {
fillHelper(list);
}
private static <T> void fillHelper(List<T> list) {
// Fill with null (default for reference types)
for (int i = 0; i < list.size(); i++) {
list.set(i, null);
}
}
}
List<String> data = new ArrayList<>(Arrays.asList("x", "y", "z"));
System.out.println(" Before: " + data);
Filler.fillWithDefault(data);
System.out.println(" After: " + data);
System.out.println("\nRemove duplicates:");
class Deduplicator {
public static void removeDuplicates(List<?> list) {
removeDuplicatesHelper(list);
}
private static <T> void removeDuplicatesHelper(List<T> list) {
Set<T> seen = new HashSet<>();
Iterator<T> it = list.iterator();
while (it.hasNext()) {
T item = it.next();
if (!seen.add(item)) {
it.remove();
}
}
}
}
List<Integer> duplicates = new ArrayList<>(
Arrays.asList(1, 2, 2, 3, 1, 4, 3, 5));
System.out.println(" Before: " + duplicates);
Deduplicator.removeDuplicates(duplicates);
System.out.println(" After: " + duplicates);
}
}
import java.util.*;
public class Capture {
public static void reverse(List<?> list) {
reverseHelper(list); // Capture wildcard
}
private static <T> void reverseHelper(List<T> list) {
// Now T is a concrete captured type
int size = list.size();
for (int i = 0; i < size / 2; i++) {
T temp = list.get(i);
list.set(i, list.get(size - 1 - i));
list.set(size - 1 - i, temp);
}
}
public static void main(String[] args) {
System.out.println("Wildcard capture:\n");
List<Integer> ints = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
System.out.println(" Before: " + ints);
reverse(ints);
System.out.println(" After: " + ints);
List<String> strs = new ArrayList<>(Arrays.asList("a", "b", "c"));
System.out.println(" Before: " + strs);
reverse(strs);
System.out.println(" After: " + strs);
// Cannot manipulate elements in List<?> directly
// Use helper method with <T> to "capture" the type
// Helper method sees concrete type T
// Enables operations that need consistent type
System.out.println("\nSwap elements:");
class Swapper {
public static void swap(List<?> list, int i, int j) {
swapHelper(list, i, j);
}
private static <T> void swapHelper(List<T> list, int i, int j) {
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
List<Integer> numbers = new ArrayList<>(Arrays.asList(10, 20, 30, 40));
System.out.println(" Before: " + numbers);
Swapper.swap(numbers, 0, 3);
System.out.println(" After: " + numbers);
System.out.println("\nRotate list:");
class Rotator {
public static void rotate(List<?> list, int distance) {
rotateHelper(list, distance);
}
private static <T> void rotateHelper(List<T> list, int distance) {
int size = list.size();
if (size == 0) return;
distance = distance % size;
if (distance < 0) distance += size;
for (int i = 0; i < distance; i++) {
T last = list.remove(size - 1);
list.add(0, last);
}
}
}
List<String> words = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
System.out.println(" Before: " + words);
int rotateDistance = -1;
Rotator.rotate(words, rotateDistance);
System.out.println(" After: " + words);
System.out.println("\nShuffle:");
class Shuffler {
public static void shuffle(List<?> list) {
shuffleHelper(list);
}
private static <T> void shuffleHelper(List<T> list) {
Random random = new Random(42);
for (int i = list.size() - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
}
List<Integer> deck = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
System.out.println(" Before: " + deck);
Shuffler.shuffle(deck);
System.out.println(" After: " + deck);
System.out.println("\nFill with default:");
class Filler {
public static void fillWithDefault(List<?> list) {
fillHelper(list);
}
private static <T> void fillHelper(List<T> list) {
// Fill with null (default for reference types)
for (int i = 0; i < list.size(); i++) {
list.set(i, null);
}
}
}
List<String> data = new ArrayList<>(Arrays.asList("x", "y", "z"));
System.out.println(" Before: " + data);
Filler.fillWithDefault(data);
System.out.println(" After: " + data);
System.out.println("\nRemove duplicates:");
class Deduplicator {
public static void removeDuplicates(List<?> list) {
removeDuplicatesHelper(list);
}
private static <T> void removeDuplicatesHelper(List<T> list) {
Set<T> seen = new HashSet<>();
Iterator<T> it = list.iterator();
while (it.hasNext()) {
T item = it.next();
if (!seen.add(item)) {
it.remove();
}
}
}
}
List<Integer> duplicates = new ArrayList<>(
Arrays.asList(1, 2, 2, 3, 1, 4, 3, 5));
System.out.println(" Before: " + duplicates);
Deduplicator.removeDuplicates(duplicates);
System.out.println(" After: " + duplicates);
}
}
import java.util.*;
public class Capture {
public static void reverse(List<?> list) {
reverseHelper(list); // Capture wildcard
}
private static <T> void reverseHelper(List<T> list) {
// Now T is a concrete captured type
int size = list.size();
for (int i = 0; i < size / 2; i++) {
T temp = list.get(i);
list.set(i, list.get(size - 1 - i));
list.set(size - 1 - i, temp);
}
}
public static void main(String[] args) {
System.out.println("Wildcard capture:\n");
List<Integer> ints = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
System.out.println(" Before: " + ints);
reverse(ints);
System.out.println(" After: " + ints);
List<String> strs = new ArrayList<>(Arrays.asList("a", "b", "c"));
System.out.println(" Before: " + strs);
reverse(strs);
System.out.println(" After: " + strs);
// Cannot manipulate elements in List<?> directly
// Use helper method with <T> to "capture" the type
// Helper method sees concrete type T
// Enables operations that need consistent type
System.out.println("\nSwap elements:");
class Swapper {
public static void swap(List<?> list, int i, int j) {
swapHelper(list, i, j);
}
private static <T> void swapHelper(List<T> list, int i, int j) {
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
List<Integer> numbers = new ArrayList<>(Arrays.asList(10, 20, 30, 40));
System.out.println(" Before: " + numbers);
Swapper.swap(numbers, 0, 3);
System.out.println(" After: " + numbers);
System.out.println("\nRotate list:");
class Rotator {
public static void rotate(List<?> list, int distance) {
rotateHelper(list, distance);
}
private static <T> void rotateHelper(List<T> list, int distance) {
int size = list.size();
if (size == 0) return;
distance = distance % size;
if (distance < 0) distance += size;
for (int i = 0; i < distance; i++) {
T last = list.remove(size - 1);
list.add(0, last);
}
}
}
List<String> words = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
System.out.println(" Before: " + words);
int rotateDistance = 1;
Rotator.rotate(words, rotateDistance);
System.out.println(" After: " + words);
System.out.println("\nShuffle:");
class Shuffler {
public static void shuffle(List<?> list) {
shuffleHelper(list);
}
private static <T> void shuffleHelper(List<T> list) {
Random random = new Random(42);
for (int i = list.size() - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
}
List<Integer> deck = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
System.out.println(" Before: " + deck);
Shuffler.shuffle(deck);
System.out.println(" After: " + deck);
System.out.println("\nFill with default:");
class Filler {
public static void fillWithDefault(List<?> list) {
fillHelper(list);
}
private static <T> void fillHelper(List<T> list) {
// Fill with null (default for reference types)
for (int i = 0; i < list.size(); i++) {
list.set(i, null);
}
}
}
List<String> data = new ArrayList<>(Arrays.asList("x", "y", "z"));
System.out.println(" Before: " + data);
Filler.fillWithDefault(data);
System.out.println(" After: " + data);
System.out.println("\nRemove duplicates:");
class Deduplicator {
public static void removeDuplicates(List<?> list) {
removeDuplicatesHelper(list);
}
private static <T> void removeDuplicatesHelper(List<T> list) {
Set<T> seen = new HashSet<>();
Iterator<T> it = list.iterator();
while (it.hasNext()) {
T item = it.next();
if (!seen.add(item)) {
it.remove();
}
}
}
}
List<Integer> duplicates = new ArrayList<>(
Arrays.asList(1, 2, 2, 3, 1, 4, 3, 5));
System.out.println(" Before: " + duplicates);
Deduplicator.removeDuplicates(duplicates);
System.out.println(" After: " + duplicates);
}
}
public static void main(String[] args)
18public static void main(String[] args) {19 System.out.println("Wildcard capture:\n");20 21 List<Integer> ints = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));22 System.out.println(" Before: " + ints[1, 2, 3, 4, 5]);23 reverse(ints);outputWildcard capture: Wildcard capture: Before: [1, 2, 3, 4, 5] Before: [1, 2, 3, 4, 5]public static void reverse(List<?> list)
pass 1 of 23public class Capture {4 public static void reverse(List<?> list[1, 2, 3, 4, 5]) {5 reverseHelper(list[1, 2, 3, 4, 5]); // Capture wildcard6 }size ← 5
pass 1 of 28private static <T> void reverseHelper(List<T> list[1, 2, 3, 4, 5]) {9 // Now T is a concrete captured type10 int size→ 5 = list.size();11 for (int i = 0; i < size / 2; i++) {temp ← 1
pass 1 of 310int size = list.size();11for (int i0 = 0; i < size5 / 2; i++) {12 T temp→ 1 = list.get(i0);13 list.set(i0, list.get(size5 - 1 - i));14 list.set(size5 - 1 - i0, temp1);15}All 3 passes — pass 1 is the card above pass isizetemplist1 0 5 1 — 2 1 5 2 [1, 2, 3, 4, 5] → [5, 4, 3, 2, 1] 3 0 3 a [a, b, c] → [c, b, a] System.out.println(" After: " + ints);
23reverse(ints);24System.out.println(" After: " + ints[5, 4, 3, 2, 1]);2526List<String> strs = new ArrayList<>(Arrays.asList("a", "b", "c"));27System.out.println(" Before: " + strs[a, b, c]);28reverse(strs);output After: [5, 4, 3, 2, 1] After: [5, 4, 3, 2, 1] Before: [a, b, c] Before: [a, b, c]public static void reverse(List<?> list)
pass 2 of 23public class Capture {4 public static void reverse(List<?> list[a, b, c]) {5 reverseHelper(list[a, b, c]); // Capture wildcard6 }size ← 3
pass 2 of 28private static <T> void reverseHelper(List<T> list[a, b, c]) {9 // Now T is a concrete captured type10 int size→ 3 = list.size();11 for (int i = 0; i < size / 2; i++) {System.out.println(" After: " + strs);
28reverse(strs);29System.out.println(" After: " + strs[c, b, a]);3031// Cannot manipulate elements in List<?> directly32// Use helper method with <T> to "capture" the type33// Helper method sees concrete type T34// Enables operations that need consistent type3536System.out.println("\nSwap elements:");3738class Swapper {39 public static void swap(List<?> list, int i, int j) {40 swapHelper(list, i, j);41 }42 43 private static <T> void swapHelper(List<T> list, int i, int j) {44 T temp = list.get(i);45 list.set(i, list.get(j));46 list.set(j, temp);47 }48}4950List<Integer> numbers = new ArrayList<>(Arrays.asList(10, 20, 30, 40));51System.out.println(" Before: " + numbers[10, 20, 30, 40]);52Swapper.swap(numbers, 0, 3);output After: [c, b, a] After: [c, b, a] Swap elements: Swap elements: Before: [10, 20, 30, 40] Before: [10, 20, 30, 40]public static void swap(List<?> list, int i, int j)
38class Swapper {39 public static void swap(List<?> list[10, 20, 30, 40], int i0, int j3) {40 swapHelper(list[10, 20, 30, 40], i0, j3);41 }temp ← 10, list ← [40, 20, 30, 10]
39public static void swap(List<?> list, int i, int j) {40 swapHelper(list→ [40, 20, 30, 10], i0, j3);41}4243private static <T> void swapHelper(List<T> list[10, 20, 30, 40], int i0, int j3) {44 T temp→ 10 = list.get(i0);45 list.set(i0, list.get(j3));46 list.set(j3, temp10);47}System.out.println(" After: " + numbers);
52Swapper.swap(numbers, 0, 3);53System.out.println(" After: " + numbers[40, 20, 30, 10]);5455System.out.println("\nRotate list:");5657class Rotator {58 public static void rotate(List<?> list, int distance) {59 rotateHelper(list, distance);60 }61 62 private static <T> void rotateHelper(List<T> list, int distance) {63 int size = list.size();64 if (size == 0) return;65 66 distance = distance % size;67 if (distance < 0) distance += size;68 69 for (int i = 0; i < distance; i++) {70 T last = list.remove(size - 1);71 list.add(0, last);72 }73 }74}7576List<String> words = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));77System.out.println(" Before: " + words[A, B, C, D, E]);78int rotateDistance = 2; //@rotateDistance=2, 1, -1output After: [40, 20, 30, 10] After: [40, 20, 30, 10] Rotate list: Rotate list: Before: [A, B, C, D, E] Before: [A, B, C, D, E]public static void rotate(List<?> list, int distance)
57class Rotator {58 public static void rotate(List<?> list[A, B, C, D, E], int distance2) {59 rotateHelper(list[A, B, C, D, E], distance2);60 }size ← 5, distance ← 2
62private static <T> void rotateHelper(List<T> list[A, B, C, D, E], int distance2) {63 int size→ 5 = list.size();64 if (size == 0) return;65 66 distance→ 2 = distance % size5;67 if (distance < 0) distance += size;last ← E
pass 1 of 269for (int i0 = 0; i < distance2; i++) {70 T last→ E = list.remove(size5 - 1);71 list.add(0, lastE);72}last ← D, list ← [D, E, A, B, C]
pass 2 of 258public static void rotate(List<?> list, int distance) {59 rotateHelper(list→ [D, E, A, B, C], distance2);60}6162private static <T> void rotateHelper(List<T> list, int distance) {63 int size = list.size();64 if (size == 0) return;65 66 distance = distance % size;67 if (distance < 0) distance += size;68 69 for (int i1 = 0; i < distance2; i++) {70 T last→ D = list.remove(size5 - 1);71 list.add(0, lastD);72 }System.out.println(" After: " + words);
79Rotator.rotate(words, rotateDistance);80System.out.println(" After: " + words[D, E, A, B, C]);8182System.out.println("\nShuffle:");8384class Shuffler {85 public static void shuffle(List<?> list) {86 shuffleHelper(list);87 }88 89 private static <T> void shuffleHelper(List<T> list) {90 Random random = new Random(42);91 for (int i = list.size() - 1; i > 0; i--) {92 int j = random.nextInt(i + 1);93 T temp = list.get(i);94 list.set(i, list.get(j));95 list.set(j, temp);96 }97 }98}99100List<Integer> deck = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));101System.out.println(" Before: " + deck[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);102Shuffler.shuffle(deck);output After: [D, E, A, B, C] After: [D, E, A, B, C] Shuffle: Shuffle: Before: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Before: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]public static void shuffle(List<?> list)
84class Shuffler {85 public static void shuffle(List<?> list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) {86 shuffleHelper(list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);87 }random ← ⟨Random A⟩
89private static <T> void shuffleHelper(List<T> list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) {90 Random random→ ⟨Random A⟩ = new Random(42);91 for (int i = list.size() - 1; i > 0; i--) {j ← 0, temp ← 10
pass 1 of 990Random random = new Random(42);91for (int i9 = list.size() - 1; i > 0; i--) {92 int j→ 0 = random.nextInt(i9 + 1);93 T temp→ 10 = list.get(i9);94 list.set(i9, list.get(j0));95 list.set(j0, temp10);96}All 9 passes — pass 1 is the card above pass ijtemplist1 9 0 10 — 2 8 3 9 — 3 7 5 8 — 4 6 3 7 — 5 5 0 8 — 6 4 0 5 — 7 3 1 7 — 8 2 2 3 — 9 1 1 7 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] → [5, 7, 3, 2, 8, 10, 9, 6, 4, 1] System.out.println(" After: " + deck);
102Shuffler.shuffle(deck);103System.out.println(" After: " + deck[5, 7, 3, 2, 8, 10, 9, 6, 4, 1]);104105System.out.println("\nFill with default:");106107class Filler {108 public static void fillWithDefault(List<?> list) {109 fillHelper(list);110 }111 112 private static <T> void fillHelper(List<T> list) {113 // Fill with null (default for reference types)114 for (int i = 0; i < list.size(); i++) {115 list.set(i, null);116 }117 }118}119120List<String> data = new ArrayList<>(Arrays.asList("x", "y", "z"));121System.out.println(" Before: " + data[x, y, z]);122Filler.fillWithDefault(data);output After: [5, 7, 3, 2, 8, 10, 9, 6, 4, 1] After: [5, 7, 3, 2, 8, 10, 9, 6, 4, 1] Fill with default: Fill with default: Before: [x, y, z] Before: [x, y, z]public static void fillWithDefault(List<?> list)
107class Filler {108 public static void fillWithDefault(List<?> list[x, y, z]) {109 fillHelper(list[x, y, z]);110 }private static <T> void fillHelper(List<T> list)
112private static <T> void fillHelper(List<T> list[x, y, z]) {113 // Fill with null (default for reference types)for (int i = 0; i < list.size(); i++)
pass 1 of 3113// Fill with null (default for reference types)114for (int i0 = 0; i < list.size(); i++) {115 list.set(i0, null);116}All 3 passes — pass 1 is the card above pass ilist1 0 — 2 1 — 3 2 [x, y, z] → [null, null, null] System.out.println(" After: " + data);
122Filler.fillWithDefault(data);123System.out.println(" After: " + data[null, null, null]);124125System.out.println("\nRemove duplicates:");126127class Deduplicator {128 public static void removeDuplicates(List<?> list) {129 removeDuplicatesHelper(list);130 }131 132 private static <T> void removeDuplicatesHelper(List<T> list) {133 Set<T> seen = new HashSet<>();134 Iterator<T> it = list.iterator();135 while (it.hasNext()) {136 T item = it.next();137 if (!seen.add(item)) {138 it.remove();139 }140 }141 }142}143144List<Integer> duplicates = new ArrayList<>(145 Arrays.asList(1, 2, 2, 3, 1, 4, 3, 5));146System.out.println(" Before: " + duplicates[1, 2, 2, 3, 1, 4, 3, 5]);147Deduplicator.removeDuplicates(duplicates[1, 2, 2, 3, 1, 4, 3, 5]);148System.out.println(" After: " + duplicates);output After: [null, null, null] After: [null, null, null] Remove duplicates: Remove duplicates: Before: [1, 2, 2, 3, 1, 4, 3, 5]public static void removeDuplicates(List<?> list)
127class Deduplicator {128 public static void removeDuplicates(List<?> list[1, 2, 2, 3, 1, 4, 3, 5]) {129 removeDuplicatesHelper(list[1, 2, 2, 3, 1, 4, 3, 5]);130 }seen ← [], it ← ⟨ArrayList$Itr B⟩
132private static <T> void removeDuplicatesHelper(List<T> list[1, 2, 2, 3, 1, 4, 3, 5]) {133 Set<T> seen→ [] = new HashSet<>();134 Iterator<T> it→ ⟨ArrayList$Itr B⟩ = list.iterator();135 while (it.hasNext()) {item ← 1
pass 1 of 8134Iterator<T> it = list.iterator();135while (it.hasNext()) {136 T item→ 1 = it.next();137 if (!seen.add(item)) {All 8 passes — pass 1 is the card above pass itemlist1 1 — 2 2 — 3 2 — 4 3 — 5 1 — 6 4 — 7 3 — 8 5 [1, 2, 2, 3, 1, 4, 3, 5] → [1, 2, 3, 4, 5] if (!seen.add(item))
pass 1 of 3136T item = it.next();137if (!seen.add(item2)) {138 it.remove();139}All 3 passes — pass 1 is the card above pass item1 2 2 1 3 3 duplicates ← [1, 2, 3, 4, 5]
146 System.out.println(" Before: " + duplicates);147 Deduplicator.removeDuplicates(duplicates→ [1, 2, 3, 4, 5]);148 System.out.println(" After: " + duplicates[1, 2, 3, 4, 5]);149}output After: [1, 2, 3, 4, 5]
public static void main(String[] args)
18public static void main(String[] args) {19 System.out.println("Wildcard capture:\n");20 21 List<Integer> ints = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));22 System.out.println(" Before: " + ints[1, 2, 3, 4, 5]);23 reverse(ints);outputWildcard capture: Wildcard capture: Before: [1, 2, 3, 4, 5] Before: [1, 2, 3, 4, 5]public static void reverse(List<?> list)
pass 1 of 23public class Capture {4 public static void reverse(List<?> list[1, 2, 3, 4, 5]) {5 reverseHelper(list[1, 2, 3, 4, 5]); // Capture wildcard6 }size ← 5
pass 1 of 28private static <T> void reverseHelper(List<T> list[1, 2, 3, 4, 5]) {9 // Now T is a concrete captured type10 int size→ 5 = list.size();11 for (int i = 0; i < size / 2; i++) {temp ← 1
pass 1 of 310int size = list.size();11for (int i0 = 0; i < size5 / 2; i++) {12 T temp→ 1 = list.get(i0);13 list.set(i0, list.get(size5 - 1 - i));14 list.set(size5 - 1 - i0, temp1);15}All 3 passes — pass 1 is the card above pass isizetemplist1 0 5 1 — 2 1 5 2 [1, 2, 3, 4, 5] → [5, 4, 3, 2, 1] 3 0 3 a [a, b, c] → [c, b, a] System.out.println(" After: " + ints);
23reverse(ints);24System.out.println(" After: " + ints[5, 4, 3, 2, 1]);2526List<String> strs = new ArrayList<>(Arrays.asList("a", "b", "c"));27System.out.println(" Before: " + strs[a, b, c]);28reverse(strs);output After: [5, 4, 3, 2, 1] After: [5, 4, 3, 2, 1] Before: [a, b, c] Before: [a, b, c]public static void reverse(List<?> list)
pass 2 of 23public class Capture {4 public static void reverse(List<?> list[a, b, c]) {5 reverseHelper(list[a, b, c]); // Capture wildcard6 }size ← 3
pass 2 of 28private static <T> void reverseHelper(List<T> list[a, b, c]) {9 // Now T is a concrete captured type10 int size→ 3 = list.size();11 for (int i = 0; i < size / 2; i++) {System.out.println(" After: " + strs);
28reverse(strs);29System.out.println(" After: " + strs[c, b, a]);3031// Cannot manipulate elements in List<?> directly32// Use helper method with <T> to "capture" the type33// Helper method sees concrete type T34// Enables operations that need consistent type3536System.out.println("\nSwap elements:");3738class Swapper {39 public static void swap(List<?> list, int i, int j) {40 swapHelper(list, i, j);41 }42 43 private static <T> void swapHelper(List<T> list, int i, int j) {44 T temp = list.get(i);45 list.set(i, list.get(j));46 list.set(j, temp);47 }48}4950List<Integer> numbers = new ArrayList<>(Arrays.asList(10, 20, 30, 40));51System.out.println(" Before: " + numbers[10, 20, 30, 40]);52Swapper.swap(numbers, 0, 3);output After: [c, b, a] After: [c, b, a] Swap elements: Swap elements: Before: [10, 20, 30, 40] Before: [10, 20, 30, 40]public static void swap(List<?> list, int i, int j)
38class Swapper {39 public static void swap(List<?> list[10, 20, 30, 40], int i0, int j3) {40 swapHelper(list[10, 20, 30, 40], i0, j3);41 }temp ← 10, list ← [40, 20, 30, 10]
39public static void swap(List<?> list, int i, int j) {40 swapHelper(list→ [40, 20, 30, 10], i0, j3);41}4243private static <T> void swapHelper(List<T> list[10, 20, 30, 40], int i0, int j3) {44 T temp→ 10 = list.get(i0);45 list.set(i0, list.get(j3));46 list.set(j3, temp10);47}System.out.println(" After: " + numbers);
52Swapper.swap(numbers, 0, 3);53System.out.println(" After: " + numbers[40, 20, 30, 10]);5455System.out.println("\nRotate list:");5657class Rotator {58 public static void rotate(List<?> list, int distance) {59 rotateHelper(list, distance);60 }61 62 private static <T> void rotateHelper(List<T> list, int distance) {63 int size = list.size();64 if (size == 0) return;65 66 distance = distance % size;67 if (distance < 0) distance += size;68 69 for (int i = 0; i < distance; i++) {70 T last = list.remove(size - 1);71 list.add(0, last);72 }73 }74}7576List<String> words = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));77System.out.println(" Before: " + words[A, B, C, D, E]);78int rotateDistance = -1;output After: [40, 20, 30, 10] After: [40, 20, 30, 10] Rotate list: Rotate list: Before: [A, B, C, D, E] Before: [A, B, C, D, E]public static void rotate(List<?> list, int distance)
57class Rotator {58 public static void rotate(List<?> list[A, B, C, D, E], int distance-1) {59 rotateHelper(list[A, B, C, D, E], distance-1);60 }size ← 5, distance ← -1
62private static <T> void rotateHelper(List<T> list[A, B, C, D, E], int distance-1) {63 int size→ 5 = list.size();64 if (size == 0) return;65 66 distance→ -1 = distance % size5;67 if (distance < 0) distance += size;distance ← 4
66distance = distance % size;67if (distance-1 < 0) distance += size5;last ← E
pass 1 of 469for (int i0 = 0; i < distance4; i++) {70 T last→ E = list.remove(size5 - 1);71 list.add(0, lastE);72}All 4 passes — pass 1 is the card above pass ilastlist1 0 E — 2 1 D — 3 2 C — 4 3 B [A, B, C, D, E] → [B, C, D, E, A] System.out.println(" After: " + words);
79Rotator.rotate(words, rotateDistance);80System.out.println(" After: " + words[B, C, D, E, A]);8182System.out.println("\nShuffle:");8384class Shuffler {85 public static void shuffle(List<?> list) {86 shuffleHelper(list);87 }88 89 private static <T> void shuffleHelper(List<T> list) {90 Random random = new Random(42);91 for (int i = list.size() - 1; i > 0; i--) {92 int j = random.nextInt(i + 1);93 T temp = list.get(i);94 list.set(i, list.get(j));95 list.set(j, temp);96 }97 }98}99100List<Integer> deck = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));101System.out.println(" Before: " + deck[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);102Shuffler.shuffle(deck);output After: [B, C, D, E, A] After: [B, C, D, E, A] Shuffle: Shuffle: Before: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Before: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]public static void shuffle(List<?> list)
84class Shuffler {85 public static void shuffle(List<?> list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) {86 shuffleHelper(list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);87 }random ← ⟨Random A⟩
89private static <T> void shuffleHelper(List<T> list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) {90 Random random→ ⟨Random A⟩ = new Random(42);91 for (int i = list.size() - 1; i > 0; i--) {j ← 0, temp ← 10
pass 1 of 990Random random = new Random(42);91for (int i9 = list.size() - 1; i > 0; i--) {92 int j→ 0 = random.nextInt(i9 + 1);93 T temp→ 10 = list.get(i9);94 list.set(i9, list.get(j0));95 list.set(j0, temp10);96}All 9 passes — pass 1 is the card above pass ijtemplist1 9 0 10 — 2 8 3 9 — 3 7 5 8 — 4 6 3 7 — 5 5 0 8 — 6 4 0 5 — 7 3 1 7 — 8 2 2 3 — 9 1 1 7 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] → [5, 7, 3, 2, 8, 10, 9, 6, 4, 1] System.out.println(" After: " + deck);
102Shuffler.shuffle(deck);103System.out.println(" After: " + deck[5, 7, 3, 2, 8, 10, 9, 6, 4, 1]);104105System.out.println("\nFill with default:");106107class Filler {108 public static void fillWithDefault(List<?> list) {109 fillHelper(list);110 }111 112 private static <T> void fillHelper(List<T> list) {113 // Fill with null (default for reference types)114 for (int i = 0; i < list.size(); i++) {115 list.set(i, null);116 }117 }118}119120List<String> data = new ArrayList<>(Arrays.asList("x", "y", "z"));121System.out.println(" Before: " + data[x, y, z]);122Filler.fillWithDefault(data);output After: [5, 7, 3, 2, 8, 10, 9, 6, 4, 1] After: [5, 7, 3, 2, 8, 10, 9, 6, 4, 1] Fill with default: Fill with default: Before: [x, y, z] Before: [x, y, z]public static void fillWithDefault(List<?> list)
107class Filler {108 public static void fillWithDefault(List<?> list[x, y, z]) {109 fillHelper(list[x, y, z]);110 }private static <T> void fillHelper(List<T> list)
112private static <T> void fillHelper(List<T> list[x, y, z]) {113 // Fill with null (default for reference types)for (int i = 0; i < list.size(); i++)
pass 1 of 3113// Fill with null (default for reference types)114for (int i0 = 0; i < list.size(); i++) {115 list.set(i0, null);116}All 3 passes — pass 1 is the card above pass ilist1 0 — 2 1 — 3 2 [x, y, z] → [null, null, null] System.out.println(" After: " + data);
122Filler.fillWithDefault(data);123System.out.println(" After: " + data[null, null, null]);124125System.out.println("\nRemove duplicates:");126127class Deduplicator {128 public static void removeDuplicates(List<?> list) {129 removeDuplicatesHelper(list);130 }131 132 private static <T> void removeDuplicatesHelper(List<T> list) {133 Set<T> seen = new HashSet<>();134 Iterator<T> it = list.iterator();135 while (it.hasNext()) {136 T item = it.next();137 if (!seen.add(item)) {138 it.remove();139 }140 }141 }142}143144List<Integer> duplicates = new ArrayList<>(145 Arrays.asList(1, 2, 2, 3, 1, 4, 3, 5));146System.out.println(" Before: " + duplicates[1, 2, 2, 3, 1, 4, 3, 5]);147Deduplicator.removeDuplicates(duplicates[1, 2, 2, 3, 1, 4, 3, 5]);148System.out.println(" After: " + duplicates);output After: [null, null, null] After: [null, null, null] Remove duplicates: Remove duplicates: Before: [1, 2, 2, 3, 1, 4, 3, 5]public static void removeDuplicates(List<?> list)
127class Deduplicator {128 public static void removeDuplicates(List<?> list[1, 2, 2, 3, 1, 4, 3, 5]) {129 removeDuplicatesHelper(list[1, 2, 2, 3, 1, 4, 3, 5]);130 }seen ← [], it ← ⟨ArrayList$Itr B⟩
132private static <T> void removeDuplicatesHelper(List<T> list[1, 2, 2, 3, 1, 4, 3, 5]) {133 Set<T> seen→ [] = new HashSet<>();134 Iterator<T> it→ ⟨ArrayList$Itr B⟩ = list.iterator();135 while (it.hasNext()) {item ← 1
pass 1 of 8134Iterator<T> it = list.iterator();135while (it.hasNext()) {136 T item→ 1 = it.next();137 if (!seen.add(item)) {All 8 passes — pass 1 is the card above pass itemlist1 1 — 2 2 — 3 2 — 4 3 — 5 1 — 6 4 — 7 3 — 8 5 [1, 2, 2, 3, 1, 4, 3, 5] → [1, 2, 3, 4, 5] if (!seen.add(item))
pass 1 of 3136T item = it.next();137if (!seen.add(item2)) {138 it.remove();139}All 3 passes — pass 1 is the card above pass item1 2 2 1 3 3 duplicates ← [1, 2, 3, 4, 5]
146 System.out.println(" Before: " + duplicates);147 Deduplicator.removeDuplicates(duplicates→ [1, 2, 3, 4, 5]);148 System.out.println(" After: " + duplicates[1, 2, 3, 4, 5]);149}output After: [1, 2, 3, 4, 5]
public static void main(String[] args)
18public static void main(String[] args) {19 System.out.println("Wildcard capture:\n");20 21 List<Integer> ints = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));22 System.out.println(" Before: " + ints[1, 2, 3, 4, 5]);23 reverse(ints);outputWildcard capture: Wildcard capture: Before: [1, 2, 3, 4, 5] Before: [1, 2, 3, 4, 5]public static void reverse(List<?> list)
pass 1 of 23public class Capture {4 public static void reverse(List<?> list[1, 2, 3, 4, 5]) {5 reverseHelper(list[1, 2, 3, 4, 5]); // Capture wildcard6 }size ← 5
pass 1 of 28private static <T> void reverseHelper(List<T> list[1, 2, 3, 4, 5]) {9 // Now T is a concrete captured type10 int size→ 5 = list.size();11 for (int i = 0; i < size / 2; i++) {temp ← 1
pass 1 of 310int size = list.size();11for (int i0 = 0; i < size5 / 2; i++) {12 T temp→ 1 = list.get(i0);13 list.set(i0, list.get(size5 - 1 - i));14 list.set(size5 - 1 - i0, temp1);15}All 3 passes — pass 1 is the card above pass isizetemplist1 0 5 1 — 2 1 5 2 [1, 2, 3, 4, 5] → [5, 4, 3, 2, 1] 3 0 3 a [a, b, c] → [c, b, a] System.out.println(" After: " + ints);
23reverse(ints);24System.out.println(" After: " + ints[5, 4, 3, 2, 1]);2526List<String> strs = new ArrayList<>(Arrays.asList("a", "b", "c"));27System.out.println(" Before: " + strs[a, b, c]);28reverse(strs);output After: [5, 4, 3, 2, 1] After: [5, 4, 3, 2, 1] Before: [a, b, c] Before: [a, b, c]public static void reverse(List<?> list)
pass 2 of 23public class Capture {4 public static void reverse(List<?> list[a, b, c]) {5 reverseHelper(list[a, b, c]); // Capture wildcard6 }size ← 3
pass 2 of 28private static <T> void reverseHelper(List<T> list[a, b, c]) {9 // Now T is a concrete captured type10 int size→ 3 = list.size();11 for (int i = 0; i < size / 2; i++) {System.out.println(" After: " + strs);
28reverse(strs);29System.out.println(" After: " + strs[c, b, a]);3031// Cannot manipulate elements in List<?> directly32// Use helper method with <T> to "capture" the type33// Helper method sees concrete type T34// Enables operations that need consistent type3536System.out.println("\nSwap elements:");3738class Swapper {39 public static void swap(List<?> list, int i, int j) {40 swapHelper(list, i, j);41 }42 43 private static <T> void swapHelper(List<T> list, int i, int j) {44 T temp = list.get(i);45 list.set(i, list.get(j));46 list.set(j, temp);47 }48}4950List<Integer> numbers = new ArrayList<>(Arrays.asList(10, 20, 30, 40));51System.out.println(" Before: " + numbers[10, 20, 30, 40]);52Swapper.swap(numbers, 0, 3);output After: [c, b, a] After: [c, b, a] Swap elements: Swap elements: Before: [10, 20, 30, 40] Before: [10, 20, 30, 40]public static void swap(List<?> list, int i, int j)
38class Swapper {39 public static void swap(List<?> list[10, 20, 30, 40], int i0, int j3) {40 swapHelper(list[10, 20, 30, 40], i0, j3);41 }temp ← 10, list ← [40, 20, 30, 10]
39public static void swap(List<?> list, int i, int j) {40 swapHelper(list→ [40, 20, 30, 10], i0, j3);41}4243private static <T> void swapHelper(List<T> list[10, 20, 30, 40], int i0, int j3) {44 T temp→ 10 = list.get(i0);45 list.set(i0, list.get(j3));46 list.set(j3, temp10);47}System.out.println(" After: " + numbers);
52Swapper.swap(numbers, 0, 3);53System.out.println(" After: " + numbers[40, 20, 30, 10]);5455System.out.println("\nRotate list:");5657class Rotator {58 public static void rotate(List<?> list, int distance) {59 rotateHelper(list, distance);60 }61 62 private static <T> void rotateHelper(List<T> list, int distance) {63 int size = list.size();64 if (size == 0) return;65 66 distance = distance % size;67 if (distance < 0) distance += size;68 69 for (int i = 0; i < distance; i++) {70 T last = list.remove(size - 1);71 list.add(0, last);72 }73 }74}7576List<String> words = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));77System.out.println(" Before: " + words[A, B, C, D, E]);78int rotateDistance = 1;output After: [40, 20, 30, 10] After: [40, 20, 30, 10] Rotate list: Rotate list: Before: [A, B, C, D, E] Before: [A, B, C, D, E]public static void rotate(List<?> list, int distance)
57class Rotator {58 public static void rotate(List<?> list[A, B, C, D, E], int distance1) {59 rotateHelper(list[A, B, C, D, E], distance1);60 }size ← 5, distance ← 1
62private static <T> void rotateHelper(List<T> list[A, B, C, D, E], int distance1) {63 int size→ 5 = list.size();64 if (size == 0) return;65 66 distance→ 1 = distance % size5;67 if (distance < 0) distance += size;last ← E, list ← [E, A, B, C, D]
58public static void rotate(List<?> list, int distance) {59 rotateHelper(list→ [E, A, B, C, D], distance1);60}6162private static <T> void rotateHelper(List<T> list, int distance) {63 int size = list.size();64 if (size == 0) return;65 66 distance = distance % size;67 if (distance < 0) distance += size;68 69 for (int i0 = 0; i < distance1; i++) {70 T last→ E = list.remove(size5 - 1);71 list.add(0, lastE);72 }System.out.println(" After: " + words);
79Rotator.rotate(words, rotateDistance);80System.out.println(" After: " + words[E, A, B, C, D]);8182System.out.println("\nShuffle:");8384class Shuffler {85 public static void shuffle(List<?> list) {86 shuffleHelper(list);87 }88 89 private static <T> void shuffleHelper(List<T> list) {90 Random random = new Random(42);91 for (int i = list.size() - 1; i > 0; i--) {92 int j = random.nextInt(i + 1);93 T temp = list.get(i);94 list.set(i, list.get(j));95 list.set(j, temp);96 }97 }98}99100List<Integer> deck = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));101System.out.println(" Before: " + deck[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);102Shuffler.shuffle(deck);output After: [E, A, B, C, D] After: [E, A, B, C, D] Shuffle: Shuffle: Before: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Before: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]public static void shuffle(List<?> list)
84class Shuffler {85 public static void shuffle(List<?> list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) {86 shuffleHelper(list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);87 }random ← ⟨Random A⟩
89private static <T> void shuffleHelper(List<T> list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) {90 Random random→ ⟨Random A⟩ = new Random(42);91 for (int i = list.size() - 1; i > 0; i--) {j ← 0, temp ← 10
pass 1 of 990Random random = new Random(42);91for (int i9 = list.size() - 1; i > 0; i--) {92 int j→ 0 = random.nextInt(i9 + 1);93 T temp→ 10 = list.get(i9);94 list.set(i9, list.get(j0));95 list.set(j0, temp10);96}All 9 passes — pass 1 is the card above pass ijtemplist1 9 0 10 — 2 8 3 9 — 3 7 5 8 — 4 6 3 7 — 5 5 0 8 — 6 4 0 5 — 7 3 1 7 — 8 2 2 3 — 9 1 1 7 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] → [5, 7, 3, 2, 8, 10, 9, 6, 4, 1] System.out.println(" After: " + deck);
102Shuffler.shuffle(deck);103System.out.println(" After: " + deck[5, 7, 3, 2, 8, 10, 9, 6, 4, 1]);104105System.out.println("\nFill with default:");106107class Filler {108 public static void fillWithDefault(List<?> list) {109 fillHelper(list);110 }111 112 private static <T> void fillHelper(List<T> list) {113 // Fill with null (default for reference types)114 for (int i = 0; i < list.size(); i++) {115 list.set(i, null);116 }117 }118}119120List<String> data = new ArrayList<>(Arrays.asList("x", "y", "z"));121System.out.println(" Before: " + data[x, y, z]);122Filler.fillWithDefault(data);output After: [5, 7, 3, 2, 8, 10, 9, 6, 4, 1] After: [5, 7, 3, 2, 8, 10, 9, 6, 4, 1] Fill with default: Fill with default: Before: [x, y, z] Before: [x, y, z]public static void fillWithDefault(List<?> list)
107class Filler {108 public static void fillWithDefault(List<?> list[x, y, z]) {109 fillHelper(list[x, y, z]);110 }private static <T> void fillHelper(List<T> list)
112private static <T> void fillHelper(List<T> list[x, y, z]) {113 // Fill with null (default for reference types)for (int i = 0; i < list.size(); i++)
pass 1 of 3113// Fill with null (default for reference types)114for (int i0 = 0; i < list.size(); i++) {115 list.set(i0, null);116}All 3 passes — pass 1 is the card above pass ilist1 0 — 2 1 — 3 2 [x, y, z] → [null, null, null] System.out.println(" After: " + data);
122Filler.fillWithDefault(data);123System.out.println(" After: " + data[null, null, null]);124125System.out.println("\nRemove duplicates:");126127class Deduplicator {128 public static void removeDuplicates(List<?> list) {129 removeDuplicatesHelper(list);130 }131 132 private static <T> void removeDuplicatesHelper(List<T> list) {133 Set<T> seen = new HashSet<>();134 Iterator<T> it = list.iterator();135 while (it.hasNext()) {136 T item = it.next();137 if (!seen.add(item)) {138 it.remove();139 }140 }141 }142}143144List<Integer> duplicates = new ArrayList<>(145 Arrays.asList(1, 2, 2, 3, 1, 4, 3, 5));146System.out.println(" Before: " + duplicates[1, 2, 2, 3, 1, 4, 3, 5]);147Deduplicator.removeDuplicates(duplicates[1, 2, 2, 3, 1, 4, 3, 5]);148System.out.println(" After: " + duplicates);output After: [null, null, null] After: [null, null, null] Remove duplicates: Remove duplicates: Before: [1, 2, 2, 3, 1, 4, 3, 5]public static void removeDuplicates(List<?> list)
127class Deduplicator {128 public static void removeDuplicates(List<?> list[1, 2, 2, 3, 1, 4, 3, 5]) {129 removeDuplicatesHelper(list[1, 2, 2, 3, 1, 4, 3, 5]);130 }seen ← [], it ← ⟨ArrayList$Itr B⟩
132private static <T> void removeDuplicatesHelper(List<T> list[1, 2, 2, 3, 1, 4, 3, 5]) {133 Set<T> seen→ [] = new HashSet<>();134 Iterator<T> it→ ⟨ArrayList$Itr B⟩ = list.iterator();135 while (it.hasNext()) {item ← 1
pass 1 of 8134Iterator<T> it = list.iterator();135while (it.hasNext()) {136 T item→ 1 = it.next();137 if (!seen.add(item)) {All 8 passes — pass 1 is the card above pass itemlist1 1 — 2 2 — 3 2 — 4 3 — 5 1 — 6 4 — 7 3 — 8 5 [1, 2, 2, 3, 1, 4, 3, 5] → [1, 2, 3, 4, 5] if (!seen.add(item))
pass 1 of 3136T item = it.next();137if (!seen.add(item2)) {138 it.remove();139}All 3 passes — pass 1 is the card above pass item1 2 2 1 3 3 duplicates ← [1, 2, 3, 4, 5]
146 System.out.println(" Before: " + duplicates);147 Deduplicator.removeDuplicates(duplicates→ [1, 2, 3, 4, 5]);148 System.out.println(" After: " + duplicates[1, 2, 3, 4, 5]);149}output After: [1, 2, 3, 4, 5]
Helper method with type parameter captures the wildcard's actual type.
Exercise: Practical.java
Build a collection copier using PECS