ITSC 2214
Data Structures & Algorithms with Lalith
Hi everyone! π This page is a Java knowledge map created to help support students in ITSC 2214 Data Structures & Algorithms at the Univeristy of North Carolina at Charlotte.
Iβm Lalith Uriti, a teaching assistant for section 004 with Dr. Dale-Marie Wilson. I put this together based on both my own experience with the course and the common questions and challenges I see students run into throughout the semester. If you ever need to reach me, feel free to email me at luriti@charlotte.edu
One thing that comes up a lot in DSA is that struggles usually arenβt about the data structures themselves β they come from gaps in Java fundamentals. Concepts like references vs. primitives, object behavior, recursion, control flow, and how Java actually executes code tend to show up everywhere in this class. Having a solid baseline understanding of Java is crucial for doing well in 2214.
This knowledge map is meant to help with that.
It visually organizes the major Java and data-structure-related concepts youβre expected to be comfortable with, shows how they break down into subtopics, and highlights how everything connects. The goal is fast recall and conceptual navigation, not step-by-step teaching or replacing lectures.
Each entry represents a concept you should recognize and understand at a high level. You can click on many entries to jump to related explanations below, letting you focus on one idea at a time while still keeping the bigger picture in mind. Think of it as a way to organize your understanding, not something you need to memorize line by line.
You can use this map to:
-
review Java fundamentals before in class quizzes and the final exam,
-
identify weak spots to focus your studying,
-
or quickly refresh concepts that show up in homework, labs, or projects.
This is a living resource! It reflects both topics Iβve already studied deeply and concepts I regularly revisit to keep my understanding sharp. Hopefully, it helps makes 2214 feel a little more manageable and connected.
Understanding Java
ββ Program lifecycle
β ββ Source code (.java)
β β ββ Human-readable Java source
β ββ Compilation (javac)
β β ββ Converts .java β .class (bytecode)
β ββ Bytecode (.class)
β β ββ Platform-independent instructions
β ββ JVM execution
β ββ Bytecode executed on target machine
β
ββ Basics
β ββ Program entry
β β ββ main(String[] args)
β β β ββ Entry point for all Java programs
β β ββ Execution order
β β ββ Top-to-bottom, statement by statement
β β
β ββ Data types and variables
β β ββ Variables
β β β ββ Named storage locations with a fixed type
β β β
β β ββ Primitive data types
β β β ββ byte (8-bit)
β β β ββ short (16-bit)
β β β ββ int (32-bit)
β β β ββ long (64-bit)
β β β ββ float (32-bit, decimal)
β β β ββ double (64-bit, decimal)
β β β ββ char (Unicode character)
β β β ββ boolean (true / false)
β β β ββ Not numeric (0 β false)
β β β
β β ββ Reference types
β β β ββ Store memory address
β β β ββ Examples: String, arrays, objects
β β β ββ Created using new
β β β
β β ββ Stack vs Heap
β β β ββ Primitives β stack (values)
β β β ββ References β stack (address) β heap (object)
β β β
β β ββ Type casting
β β β ββ Implicit (widening)
β β β β ββ int β long
β β β ββ Explicit (narrowing)
β β β β ββ long β int
β β β ββ boolean cannot be cast
β β β
β β ββ Variable scope
β β ββ Local
β β ββ Parameter
β β ββ Field
β β
β ββ Operations on primitive types
β β ββ Arithmetic (+ β * / %)
β β ββ Increment / decrement
β β β ββ Postfix (a++, a--) β use then modify
β β β ββ Prefix (++a, --a) β modify then use
β β β
β β ββ Relational operators
β β β ββ ==, !=
β β β ββ >, >=
β β β ββ <, <=
β β β
β β ββ Boolean logic
β β β ββ NOT (!) β invert
β β β ββ AND (&&) β both true
β β β ββ OR (||) β one true
β β β ββ XOR (^) β different
β β β ββ Precedence: ! β ^ β && β ||
β β β ββ Short-circuiting
β β β ββ false && β¦ β false
β β β ββ true || β¦ β true
β β β
β β ββ Assignment operators
β β ββ =, +=, -=, *=, /=, %=
β β
β ββ Control flow statements
β β ββ Conditionals
β β β ββ if / else
β β β ββ switch
β β β ββ Ternary: cond ? a : b
β β β
β β ββ Loops
β β β ββ for
β β β ββ while
β β β ββ do-while
β β β
β β ββ Branching
β β ββ break
β β ββ continue
β β
β ββ Strings
β ββ String (immutable)
β β ββ length()
β β ββ charAt(i)
β β ββ substring(i), substring(i, j)
β β ββ equals / equalsIgnoreCase
β β ββ compareTo / compareToIgnoreCase
β β ββ contains
β β ββ startsWith / endsWith
β β ββ indexOf / lastIndexOf
β β ββ toLowerCase / toUpperCase / trim
β β ββ split(regex)
β β ββ toCharArray()
β β
β ββ Character helpers
β β ββ isLetter / isDigit / isLetterOrDigit
β β ββ isUpperCase / isLowerCase
β β ββ toUpperCase / toLowerCase
β β
β ββ StringBuilder (mutable)
β ββ append(String / char / int)
β ββ setCharAt
β ββ insert
β ββ delete
β ββ toString()
β
ββ Code organization
β ββ Methods
β β ββ Declaration
β β β ββ modifiers + return + name + params + body
β β ββ Signature
β β β ββ name + parameter list
β β ββ Static vs instance
β β ββ main method
β β β ββ public static void main(String[] args)
β β ββ Method calls
β β β ββ Class.method()
β β β ββ object.method()
β β ββ Built-in vs user-defined
β β
β ββ Classes and objects
β β ββ Class β blueprint
β β ββ Object β instance
β β ββ Fields β state
β β ββ Constructors β initialization
β β ββ this β current object
β β
β ββ Inheritance (IS-A)
β ββ extends keyword
β ββ Single inheritance
β ββ Polymorphism (override)
β
ββ Working with data
β ββ Arrays
β β ββ Declaration: int[] arr
β β ββ Instantiation: new int[n]
β β ββ Default values
β β β ββ int β 0
β β β ββ boolean β false
β β β ββ reference β null
β β ββ Length: arr.length (field)
β β ββ Iteration
β β β ββ for (i < arr.length)
β β β ββ for-each
β β ββ Processing patterns
β β β ββ Search
β β β ββ Accumulate
β β β ββ Predicate check
β β ββ 2D arrays
β β ββ Nested loops
β β
β ββ Collections framework
β β ββ Iterable
β β ββ List
β β β ββ ArrayList (dynamic array)
β β β ββ LinkedList (node-based)
β β ββ Set
β β β ββ HashSet
β β ββ Map
β β ββ HashMap
β β
β ββ Searching & ordering
β β ββ Linear search
β β ββ Comparable
β β β ββ object defines compareTo
β β ββ Comparator
β β ββ external comparison logic
β β
β ββ Hashing
β β ββ char β Unicode int
β β ββ Accumulate values
β β ββ Modulo tableSize
β β
β ββ Stacks & queues
β β ββ Stack (LIFO)
β β β ββ push / pop / peek
β β β ββ Reverse, palindrome, postfix
β β ββ Queue (FIFO)
β β ββ enqueue / dequeue
β β ββ Conditional cycling
β β
β ββ Linked structures
β β ββ Node<E> (data, next)
β β ββ Build from array
β β ββ Insert / remove
β β ββ Linear search
β β
β ββ Recursion
β β ββ Base case
β β ββ Recursive case
β β ββ Math sequences
β β ββ String recursion
β β ββ Array recursion
β β ββ Tree recursion
β β
β ββ Trees
β β ββ Binary tree
β β ββ Traversals
β β β ββ Preorder (NLR)
β β β ββ Inorder (LNR)
β β β ββ Postorder (LRN)
β β ββ Properties
β β ββ Height
β β ββ Node count
β β ββ Full / complete
β β
β ββ Graphs
β ββ Representations
β β ββ Adjacency matrix
β β ββ Adjacency list
β ββ Properties
β β ββ Self loops
β β ββ Degree
β β ββ Edge count
β β ββ Complete graph
β β ββ Triangle detection
β ββ Graph algorithms
β ββ hasEdge
β ββ removeEdge
β ββ getNodeDegree
β ββ Matrix β list conversion
β
ββ Errorless code
ββ Exceptions
β ββ Checked
β ββ Unchecked
β ββ try / catch / finally
β
ββ Common runtime errors
β ββ NullPointerException
β ββ ArithmeticException
β ββ IndexOutOfBoundsException
β
ββ Testing
ββ Unit tests
ββ Assertions
ββ JUnit
Program lifecycle
Source code
Source code is the human-written form of a Java program and is where all logic is defined using Javaβs syntax and rules. These files are readable and editable by programmers but cannot be executed directly by the computer.
In real projects (especially coursework), you may be given empty or partially completed .java files to implement while other functionality already exists as compiled .class files. This separation is intentional: it allows you to write code against an existing interface or API without seeing the full implementation, which mirrors how real-world libraries are used.
When you type in VS Code, the editor is constantly analyzing your source code in the background. It checks for syntax errors, missing imports, type mismatches, and unresolved methods before you ever run the program, which is why errors and warnings appear as you type.
Compilation
Compilation is the process where the Java compiler, javac, checks .java files for syntax and type errors. If the code is valid, javac translates the source code into .class files containing bytecode.
This step is where Java becomes strict: every variable must have a type, every method call must exist, and access rules must be respected. If compilation fails, no .class file is produced, and the program cannot proceed.
When you click Run or Test in VS Code, the IDE automatically invokes javac for you behind the scenes. The success or failure of compilation directly determines whether the JVM will ever start, which is why many errors never make it to βruntime.β
Bytecode
Bytecode is the compiled output of a Java program stored in .class files. It is platform-independent and designed to run on any system that has a Java Virtual Machine.
Although .class files may show readable strings when opened in an editor, they are not human-readable source code and are not meant to be edited. What youβre seeing are embedded names, constants, and metadata that help the JVM and tools like debuggers and test frameworks understand the structure of the program.
At this stage, your program exists as structured instructions, not text logic. This is the form that libraries, testing frameworks, and the JVM itself work with.
JVM execution
JVM execution begins when a Java program is run and the Java Virtual Machine starts with a specific entry point, such as a main method or a JUnit test. The JVM does not load every class at once; instead, it loads .class files on demand as they are needed.
Each class is first verified to ensure the bytecode is safe and valid, then linked so references between classes can be resolved. Only after this does execution begin, with the JVM translating bytecode into machine code that your operating system can run.
During execution, tools like VS Code, JUnit, and the Java runtime collect information about what code is being used. When you see percentages, green checkmarks, or coverage bars, those come from testing and coverage tools that track which lines and branches of bytecode were executed during a run.
In other words, VS Code isnβt just βrunningβ your program. It is coordinating compilation, launching the JVM, running tests, observing execution, and reporting results back to you in a human-friendly way.
Java separates writing, checking, running, and observing code into clear stages, and your IDE simply automates the handoff between them.
Basics
Code organization
Working with data
Errorless code
Program entry
Every Java program begins execution at public static void main(String[] args), which serves as the JVM entry point. Statements execute top-to-bottom unless redirected by control flow constructs.
Data types and variables
Java is statically typed, meaning every variable must declare a fixed type such as int, double, or String before use. Variables represent named storage locations whose behavior depends on whether they are primitive values or object references.
Operations on primitive types
Primitive types support arithmetic, relational, and logical operations including +, ==, &&, and || with defined precedence rules. Increment and decrement operators behave differently in prefix versus postfix form.
Control flow statements
Control flow constructs such as if, switch, for, and while determine execution paths and repetition. Keywords like break and continue alter loop behavior at runtime.
Strings
String objects are immutable, meaning operations like substring() create new objects rather than modifying existing ones. StringBuilder enables efficient mutable string manipulation.
Code organization
Methods
Methods encapsulate reusable behavior and are identified by a signature consisting of a name and parameter list. Calls resolve at compile time based on static types.
Classes and objects
A class defines structure and behavior, while an object is a runtime instance created using new. Fields store state, and constructors initialize that state.
Inheritance
Inheritance establishes an IS-A relationship using extends, allowing subclasses to reuse and override behavior. Java supports single inheritance with runtime polymorphism.
Working with data
Arrays
Arrays store fixed-size sequences of same-type elements and expose their size via arr.length. Elements are automatically initialized to default values.
Collections framework
The Collections Framework provides dynamic data structures such as ArrayList, HashSet, and HashMap. Interfaces define behavior while implementations determine performance.
Searching & ordering
Linear search inspects elements sequentially, while ordering relies on Comparable or Comparator. Comparison logic determines sort order and equality semantics.
Hashing
Hashing converts data into integer indices using hashCode() and modulo arithmetic. Efficient hashing minimizes collisions and enables constant-time access.
Stacks & queues
Stacks follow LIFO behavior using push and pop, while queues follow FIFO ordering using enqueue and dequeue. These structures model controlled access patterns.
Linked structures
Linked structures store elements in Node<E> objects connected by references rather than contiguous memory. This enables efficient insertion and removal.
Recursion
Recursion solves problems by invoking a method within itself until a base case is reached. Each recursive call consumes stack space.
Trees
Trees represent hierarchical data using parent-child relationships. Traversals such as inorder and preorder define visit order.
Graphs
Graphs model arbitrary relationships using adjacency matrices or adjacency lists. Algorithms operate on edges, degrees, and connectivity.
Errorless code
Exceptions
Exceptions represent abnormal execution conditions handled using try, catch, and finally. Checked exceptions require explicit handling at compile time.
Common runtime errors
Errors such as NullPointerException and IndexOutOfBoundsException occur during execution due to invalid state or access.
Testing
Testing verifies correctness using unit tests, assertions, and frameworks like JUnit. Automated tests detect regressions early.