Strings and Data CollectionsIntroductionPrograms rarely operate on one value at a time. They process names, messages, measurements, transaction records, search results, and groups of related objects. Strings and data collections provide the fundamental structures for representing and manipulating such information. A string is an ordered sequence of characters. Collections group multiple values so that a program can traverse, select, aggregate, organize, and update data. Python provides lists, tuples, sets, and dictionaries; Java provides arrays, the ArrayList, HashSet, and HashMap classes, together with interfaces such as List, Set, and Map. Although Python and Java use different syntax and libraries, the underlying programming ideas are similar: indexing, traversal, membership testing, aggregation, mutability, and choosing an appropriate data structure. Learning ObjectivesBy the end of this chapter, you should be able to: - create, compare, concatenate, search, index, and slice strings;
- explain the difference between mutable and immutable data;
- create and traverse arrays and common collection types;
- distinguish lists, tuples, sets, dictionaries, and maps;
- perform aggregation and selection operations;
- choose a collection type based on ordering, duplication, mutability, and lookup requirements;
- write clear Python and Java code for practical data-processing tasks;
- identify common errors involving indexes, aliases, keys, and collection modification.
1. Strings as Ordered TextA string stores text as an ordered sequence of characters. In Python, strings are represented by the str type. In Java, ordinary text is represented by the String class. Both support indexing-like access conceptually, but their syntax and capabilities differ. name = "Ada Lovelace"
message = 'Welcome, ' + name
print(message) String name = "Ada Lovelace";
String message = "Welcome, " + name;
System.out.println(message); String literals may use single or double quotation marks in Python. Java uses double quotation marks for String literals; single quotation marks represent a single char value. 1.1 IndexingIndexing retrieves one character from a sequence. Python indexes from zero and also permits negative indexes. Java uses the charAt method and does not support negative indexes. word = "computer"
print(word[0]) # c
print(word[-1]) # r String word = "computer";
System.out.println(word.charAt(0));
System.out.println(word.charAt(word.length() - 1)); For a string of length n, valid Python indexes are 0 through n − 1, or −n through −1. An index outside that range causes an error. In Java, charAt throws StringIndexOutOfBoundsException when the index is invalid. 1.2 Slicing and SubstringsPython slicing extracts a portion of a sequence using the form sequence[start:stop:step]. The stop position is excluded. text = "programming"
print(text[0:4]) # prog
print(text[4:]) # ramming
print(text[:6]) # progra
print(text[::2]) # pormig The general number of selected positions for a positive step is determined by the range of indexes from start up to, but not including, stop, moving by step. A zero step is invalid. Java provides substring(beginIndex, endIndex), where the ending index is also exclusive: String text = "programming";
System.out.println(text.substring(0, 4));
System.out.println(text.substring(4)); Python slicing generally returns a new string. Java substring returns a new string value, although implementation details may vary by Java version. Neither operation changes the original string. 1.3 ImmutabilityStrings are immutable: after creation, their character contents cannot be changed in place. An operation that appears to modify a string actually creates another string. word = "cat"
word = word + "er" # a new string is assigned to word String word = "cat";
word = word + "er"; Immutability improves safety because a string shared by several parts of a program cannot be altered unexpectedly. However, repeatedly concatenating strings in a large loop may create many intermediate objects. Python programmers can collect pieces in a list and use join; Java programmers can use StringBuilder. parts = ["data", "structures", "matter"]
result = " ".join(parts) StringBuilder builder = new StringBuilder();
builder.append("data").append(" ");
builder.append("structures").append(" ");
builder.append("matter");
String result = builder.toString();1.4 Common String Operations| Operation | Python | Java |
|---|
| Length | len(s) | s.length() | | Convert to lowercase | s.lower() | s.toLowerCase() | | Convert to uppercase | s.upper() | s.toUpperCase() | | Remove outer whitespace | s.strip() | s.trim() or strip() | | Find a substring | s.find(x) | s.indexOf(x) | | Test containment | x in s | s.contains(x) | | Replace text | s.replace(a, b) | s.replace(a, b) | | Split text | s.split(delimiter) | s.split(delimiter) |
String comparisons should be chosen carefully. Python’s == compares string contents. In Java, == compares object references, so content comparison normally requires .equals(): if (username.equals("admin")) {
System.out.println(" privileged user");
}A safer form when a variable could be null is "admin".equals(username). 1.5 Traversing StringsTraversal means visiting each element in sequence. A for loop is usually clearer than manual index management. for character in "hello":
print(character)for (int i = 0; i < word.length(); i++) {
System.out.println(word.charAt(i));
}A common application is character classification. For example, a program may count vowels: text = "Education"
count = 0
for ch in text.lower():
if ch in "aeiou":
count += 1
print(count) # 5The result is 5 because the vowels are e, u, a, i, and o. The loop examines each character once, so its running time grows approximately in proportion to the string length. 2. Arrays and Indexed SequencesAn array stores a fixed number of elements of a specified type in indexed positions. Arrays are especially useful when the size is known and direct positional access is important. 2.1 Java Arraysint[] scores = {82, 91, 76, 88};
System.out.println(scores[1]); // 91
scores[2] = 79;The array length is fixed after creation: int[] values = new int[5];
System.out.println(values.length); Java arrays are zero-indexed. An array of length 5 has valid indexes 0, 1, 2, 3, and 4. Java arrays contain one declared element type, although reference-type arrays may hold objects belonging to compatible subclasses. 2.2 Python Lists as Dynamic Indexed SequencesPython does not normally use a separate built-in array type for general programming. Lists provide dynamically sized indexed sequences and may contain values of different types. scores = [82, 91, 76, 88]
print(scores[1])
scores[2] = 79
scores.append(95) Python lists support slicing, insertion, deletion, and growth. Their flexibility is convenient, but a list should not contain unrelated types merely because the language permits it. Consistent element types make programs easier to understand and test. 2.3 Traversal and Enumerated Traversalfor score in scores:
print(score)
for index, score in enumerate(scores):
print(index, score)for (int score : scores) {
System.out.println(score);
}Use an index when the position is required; otherwise, direct traversal communicates intent more clearly. 3. Python Lists and Java ListsA list is an ordered collection that normally permits duplicate values. Python’s list and Java’s List abstraction serve similar purposes. items = ["pen", "book", "pen"]
items.append("lamp")
items.remove("pen") # removes the first matching valueimport java.util.ArrayList;
import java.util.List;
List<String> items = new ArrayList<>();
items.add("pen");
items.add("book");
items.add("pen");
items.remove("pen");Java generics, such as List<String>, specify the intended element type at compile time. Python checks types at runtime and relies more heavily on testing and programming discipline. Important list operations include: - append or add an element;
- insert at a position;
- remove by value or position;
- search for membership;
- sort or reverse;
- traverse every element;
- compute an aggregate such as a total or maximum.
A list is appropriate when order matters, duplicates are meaningful, and the collection may change. 4. Tuples and Immutable RecordsA Python tuple is an ordered, immutable collection: point = (3, 7)
x, y = point Tuples are useful for fixed groups of related values, such as coordinates, database rows, or configuration records. They communicate that the collection itself should not be changed. coordinates = [(0, 0), (2, 5), (4, 1)] A tuple may contain a mutable object, so immutability applies to the tuple’s references, not necessarily to every object reachable through them. For example, a tuple containing a list still contains a list that can be changed. Java has no direct built-in tuple type. Common alternatives include a small class, a record, or a library type: record Point(int x, int y) {}
Point point = new Point(3, 7);A record is a concise way to represent a data carrier with named components. It is not identical to a Python tuple, but it often serves a similar design purpose. 5. Sets: Uniqueness and MembershipA set stores distinct elements. Sets are suitable when duplicate values have no meaning and fast membership testing is more important than positional access. languages = {"Python", "Java", "Python"}
print(languages) # contains Python and Java once each
print("Java" in languages)Sets are unordered in the conceptual data-model sense. A program should not depend on a particular iteration order unless the implementation and language documentation explicitly guarantee one. Common set operations include union, intersection, difference, and symmetric difference: required = {"loops", "strings", "functions"}
completed = {"strings", "functions", "testing"}
print(required & completed) # intersection
print(required - completed) # still required
print(required | completed) # unionJava provides Set and implementations such as HashSet, LinkedHashSet, and TreeSet: Set<String> languages = new HashSet<>();
languages.add("Python");
languages.add("Java");
languages.add("Python");HashSet is optimized for general membership operations but does not promise sorted iteration. LinkedHashSet preserves insertion order, while TreeSet maintains sorted order and requires elements to be comparable or supplied with a comparator.
Set elements must support reliable equality and hashing. If an object changes in a way that affects its hash value while it is stored in a hash-based set, membership behavior can become incorrect. This is one reason immutable values are often good set elements. 6. Dictionaries and Maps: Key–Value AssociationA dictionary or map associates each key with a value. It is appropriate when a program must look up information by an identifier rather than by numeric position. prices = {"book": 12.50, "pen": 1.75}
print(prices["book"])
prices["lamp"] = 18.00Keys are unique. Assigning a value to an existing key replaces the previous value. Python dictionaries preserve insertion order in modern Python implementations, but the main conceptual purpose remains key-based association. Safe access can use get: price = prices.get("notebook", 0.0)This returns 0.0 if the key is absent rather than raising a KeyError. Java uses the Map interface and implementations such as HashMap, LinkedHashMap, and TreeMap: Map<String, Double> prices = new HashMap<>();
prices.put("book", 12.50);
prices.put("pen", 1.75);
System.out.println(prices.get("book"));get returns null when a key is absent in a normal HashMap. Methods such as getOrDefault, containsKey, and putIfAbsent can make intent explicit.
Traversal commonly examines keys, values, or entries: for item, price in prices.items():
print(item, price)for (Map.Entry<String, Double> entry : prices.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}A map is preferable to parallel lists. Two parallel lists can become inconsistent if one is updated without the other; a map binds each key directly to its value. 7. Traversal, Selection, and Aggregation7.1 SelectionSelection retains elements satisfying a condition. Python offers comprehensions for concise transformations: scores = [55, 72, 91, 64, 48]
passes = [score for score in scores if score >= 50] The selected values are 55, 72, 91, and 64. In Java, a conventional loop is transparent at certificate level: List<Integer> passes = new ArrayList<>();
for (int score : scores) {
if (score >= 50) {
passes.add(score);
}
}Java streams can express the same operation, but a loop may be easier for beginners to debug. 7.2 TransformationTransformation creates a corresponding output value for each input value. names = ["ada", "grace", "alan"]
capitalized = [name.title() for name in names] The input is not changed. This distinction matters when several variables refer to the same mutable list. 7.3 AggregationAggregation combines many values into a result such as a count, total, minimum, maximum, or average. For numeric values x₁, x₂, …, xₙ, the arithmetic mean is: mean = (x₁ + x₂ + … + xₙ) ÷ n Here, n is the number of values and n > 0. The values must be measured on a scale for which an arithmetic mean is meaningful, and they must have compatible units. scores = [70, 80, 90]
total = sum(scores)
average = total / len(scores)
print(total, average) # 240 80.0 The average is 80.0 because 240 ÷ 3 = 80. In Java: int total = 0;
for (int score : scores) {
total += score;
}
double average = (double) total / scores.length;The cast to double is important when scores.length and total are integers; otherwise, integer division may discard the fractional part. 7.4 Filtering and Aggregation Togethertransactions = [12.50, 8.00, 25.75, 4.25]
large = [amount for amount in transactions if amount >= 10]
large_total = sum(large) The selected values are 12.50 and 25.75, so large_total is 38.25. A professional program should also validate currency assumptions, avoid inappropriate floating-point use for exact financial accounting, and consider decimal types when exact decimal representation is required. 8. Choosing an Appropriate CollectionCollection selection should follow the data’s meaning rather than personal preference. | Requirement | Suitable Python type | Suitable Java type |
|---|
| Ordered, changeable sequence | list | ArrayList / List | | Fixed ordered group | tuple | record or immutable class | | Fixed typed indexed storage | list or array-like structure | array | | Unique values | set | HashSet / Set | | Key–value lookup | dict | HashMap / Map | | Sorted unique values | set with sorting as needed | TreeSet | | Insertion-ordered map | dict | LinkedHashMap |
Ask the following questions: - Does order matter?
- Are duplicates allowed or meaningful?
- Will the collection change after creation?
- Is access primarily by position or by key?
- Is sorted order required?
- Must elements have one declared type?
- Will the program frequently test membership?
A data structure should make valid operations easy and invalid interpretations difficult. For example, a set communicates uniqueness more clearly than a list followed by repeated duplicate-removal code. 9. Aliasing, Copying, and MutationTwo variables may refer to the same mutable object. This is called aliasing. original = [1, 2, 3]
alias = original
alias.append(4)
print(original) # [1, 2, 3, 4] To create a shallow copy: copy_of_list = original.copy() A shallow copy creates a new outer list, but nested mutable objects may still be shared. Java references behave similarly: List<Integer> original = new ArrayList<>(List.of(1, 2, 3));
List<Integer> copy = new ArrayList<>(original); The copy has a separate list structure. The depth of copying required depends on whether the elements themselves are mutable objects. A frequent error is modifying a collection while traversing it. In Java, removing directly from a collection during an enhanced for loop may cause ConcurrentModificationException. Use an iterator, removeIf, or construct a filtered collection. In Python, iterate over a copy or build a new collection: values = [1, 2, 3, 4, 5]
values = [value for value in values if value % 2 == 1] 10. Applied Case: Course Results ProcessorBackgroundA training centre needs a small program to process learner results. Each learner has an identifier, a name, and several assessment scores. The program must calculate an average, identify pass status, and produce a set of learners who passed. This is an illustrative case, not a production grading system. ProblemThe program must represent: - one learner’s scores as an ordered collection;
- learner records associated with unique identifiers;
- a group of passed learner identifiers without duplicates;
- a textual report.
Python Approachlearners = {
"L101": {"name": "Amina", "scores": [72, 81, 68]},
"L102": {"name": "Jon", "scores": [45, 59, 51]},
"L103": {"name": "Mei", "scores": [88, 91, 84]}
}
passed = set()
for learner_id, record in learners.items():
scores = record["scores"]
average = sum(scores) / len(scores)
status = "Pass" if average >= 50 else "Fail"
if status == "Pass":
passed.add(learner_id)
print(f"{record['name']}: {average:.1f} ({status})")
print("Passed learners:", passed)The dictionary provides lookup by learner identifier. Each score list preserves assessment order and permits aggregation. The set ensures that a learner is recorded only once in the passed group. The averages are 73.7 for Amina, 51.7 for Jon, and 87.7 for Mei, using the displayed one-decimal rounding. All three pass under the stated threshold of 50. Analysis and Design DecisionsA list is used for scores because order and repeated values are acceptable. A dictionary is used for learner records because identifiers are keys. A set is used for passed identifiers because uniqueness is required. A tuple would be suitable if scores were deliberately fixed and immutable, but a list is more practical if scores may be corrected. Professional ConsiderationsA real system would validate that scores fall within an allowed range, handle missing scores, define rounding policy, protect personal information, and record who is authorized to view or change results. A pass threshold should be a documented policy rather than an unexplained constant. If results affect employment or progression, auditability and fairness are important. 11. Errors, Testing, and Best PracticesCommon errors include: - using index
len(sequence) as the last valid index; - confusing a string’s character count with a byte count in systems involving encodings;
- using Java
== instead of .equals() for string contents; - assuming set or hash-map traversal is sorted;
- attempting to access a missing dictionary key without handling the possibility;
- dividing by the length of an empty collection;
- changing a collection during traversal;
- sharing a mutable collection unintentionally;
- using floating-point values where exact decimal financial calculations are required.
Good practice includes descriptive names, small functions, validation at input boundaries, type-consistent collections, and tests for empty, singleton, duplicate, missing-key, and boundary-index cases. A test suite should verify both ordinary behavior and failure behavior. 12. Contemporary Development and AI-Enabled ToolsModern integrated development environments provide collection inspection, code completion, static analysis, and debugging support. AI-assisted programming tools can suggest loops, comprehensions, and library calls, but generated code must be reviewed. Particular risks include incorrect assumptions about ordering, unsafe handling of personal data, inefficient repeated concatenation, and code that silently ignores missing values. A responsible workflow is to specify the data model first, ask the tool for a limited implementation, test edge cases, inspect documentation, and retain human responsibility for correctness, privacy, and maintainability. An AI suggestion is not evidence that a collection operation has the desired semantics. Chapter SummaryStrings are immutable ordered sequences used to represent text. They support indexing, slicing or substring extraction, searching, replacement, splitting, comparison, and traversal. Python and Java differ in syntax, especially for indexing and string equality, but the underlying concepts are shared. Arrays provide fixed-size indexed storage, while lists provide flexible ordered collections that commonly allow duplicates. Tuples represent fixed ordered groups in Python, and Java records or immutable classes can serve related design purposes. Sets represent uniqueness and support membership and set operations. Dictionaries and maps associate unique keys with values and are the appropriate choice for key-based lookup. Traversal visits collection elements; selection retains values meeting a condition; transformation creates corresponding outputs; and aggregation combines values into a result. Collection choice should be based on order, duplication, mutability, access method, typing, and sorting requirements. Careful programmers also consider aliasing, copying, invalid indexes, missing keys, concurrent modification, numerical assumptions, privacy, and testing. Key TermsString: An ordered sequence of characters. Character: A single textual symbol. Index: A position used to access an element in a sequence. Slice: A selected portion of a sequence. Immutable: Unable to be changed after creation. Array: A fixed-size indexed collection, typically of one declared type. List: An ordered collection that commonly permits duplicates. Tuple: An ordered immutable collection in Python. Set: A collection of unique elements. Dictionary: A Python key–value collection. Map: A Java abstraction associating keys with values. Key: An identifier used to retrieve a mapped value. Value: Data associated with a key or stored in a collection. Traversal: Systematic visiting of collection elements. Selection: Retaining elements that satisfy a condition. Aggregation: Combining multiple values into one result. Aliasing: Multiple references to the same mutable object. Shallow copy: A copy of an outer collection whose nested references may remain shared. Mutability: The ability of an object to change after creation. Generic type: A type parameter, such as Java’s List<String>, describing permitted elements. Review QuestionsShort Answer Questions- What is the difference between indexing and slicing a string?
- Why are strings described as immutable in Python and Java?
- When is a set more suitable than a list?
- What is the purpose of a key in a dictionary or map?
- Why can aliasing cause unexpected changes to a collection?
Long Answer Questions- Compare Python lists and tuples, including their mutability, typical uses, and limitations.
- Explain the similarities and differences between a Python dictionary and a Java
Map. - Describe how traversal, selection, transformation, and aggregation work together in data processing.
- Explain the principal factors that should guide the choice between an array, list, set, and map.
- Discuss common errors in string and collection programming and propose preventive practices.
Analytical / Application Questions- Design a collection structure for an inventory system that stores unique product codes, product descriptions, and quantities. Justify each chosen type in Python and Java.
- A program stores learner scores in a list and must report the average, highest score, and all scores at least 70. Describe the algorithm and identify edge cases that must be tested.
- A developer uses a list to store usernames and repeatedly checks whether a username exists. Analyze the design and recommend an alternative if membership tests are frequent and duplicate usernames are not permitted.
Multiple Choice Questions with AnswersQuestion 1Which Python expression selects characters from index 1 up to, but not including, index 4? A. text[1:4] B. text[1:5] C. text[0:4] D. text[4:1] Correct Answer: A. text[1:4] Question 2How should Java programmatically compare the contents of two String objects? A. Using == B. Using .equals() C. Using sameReference() D. Using .compareAddress() Correct Answer: B. Using .equals() Question 3Which collection is most appropriate when duplicate values must be eliminated and membership testing is central? A. List B. Tuple C. Set D. Array Correct Answer: C. Set Question 4What is the average of the values 70, 80, and 90? A. 70 B. 75 C. 80 D. 90 Correct Answer: C. 80 Question 5What happens when a new value is assigned to an existing key in a Python dictionary? A. A duplicate key is created B. The existing value is replaced C. The dictionary becomes a set D. The assignment is always rejected Correct Answer: B. The existing value is replaced Question 6Which Python collection is ordered and immutable? A. List B. Set C. Dictionary D. Tuple Correct Answer: D. Tuple Question 7Why might Java code use StringBuilder in a loop that constructs a large string? A. It converts strings into sets B. It avoids all character encoding C. It can reduce repeated intermediate string creation D. It makes strings mutable everywhere Correct Answer: C. It can reduce repeated intermediate string creation Question 8Which structure is most directly suited to associating learner IDs with learner records? A. Map or dictionary B. Set only C. Character array only D. Tuple without keys Correct Answer: A. Map or dictionary Question 9What is the result of sum([12.50, 25.75]) in Python? A. 28.25 B. 37.25 C. 38.25 D. 40.75 Correct Answer: C. 38.25 Question 10What does aliasing mean in the context of mutable collections? A. A collection has no elements B. Two references point to the same object C. A list is automatically sorted D. A dictionary has duplicate keys Correct Answer: B. Two references point to the same object
|