100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Arrays in Julia

Learn how Julia's built-in Array type stores, indexes, and mutates collections of data, and why column-major memory layout matters for performance.

Arrays & TypesBeginner8 min readJul 10, 2026
Analogies

What Are Arrays in Julia?

In Julia, an Array is the built-in container for storing a collection of values of the same element type in a fixed-dimensional, ordered structure. The type is written Array{T,N}, where T is the element type and N is the number of dimensions — a Vector is just an alias for Array{T,1} and a Matrix for Array{T,2}. Unlike some languages that default to 0-based indexing, Julia arrays are 1-indexed by default, and Julia stores array elements in column-major order, meaning consecutive elements down a column sit next to each other in memory.

🏏

Cricket analogy: Think of a Julia Vector like a batting order card for India — every slot holds one player's name (same 'type': batsman), numbered starting at position 1 for the opener Rohit Sharma, not position 0, just like Julia's 1-based indexing.

Creating and Indexing Arrays

Arrays can be built with literal syntax like [1, 2, 3], with constructor functions such as zeros(3), ones(2, 3), or rand(4), or with comprehensions like [x^2 for x in 1:5]. Indexing uses square brackets — a[1] returns the first element and a[end] returns the last — and Julia supports range indexing such as a[2:4] to slice out a subarray. Accessing an index outside the array's bounds, such as a[10] on a three-element vector, throws a BoundsError rather than silently returning a garbage value or wrapping around.

🏏

Cricket analogy: Building an array with a comprehension is like scoring a whole fantasy XI with one formula per player automatically; but ask for player a[15] on an 11-man squad and you get a straight BoundsError, since there's no 12th batsman waiting to bat.

julia
# Creating arrays
a = [1, 2, 3]                      # Vector{Int64}
b = zeros(3)                        # 3-element Vector{Float64} of 0.0
M = ones(2, 3)                      # 2x3 Matrix{Float64} of 1.0
squares = [x^2 for x in 1:5]        # comprehension -> [1, 4, 9, 16, 25]

# Indexing
first_el = a[1]                     # 1 (1-based indexing)
last_el  = a[end]                   # 3
sub      = squares[2:4]             # [4, 9, 16]

# Out-of-bounds access throws BoundsError
# a[10]  # ERROR: BoundsError: attempt to access 3-element Vector{Int64} at index [10]

Mutating Arrays: push!, pop!, and Broadcasting Assignment

Julia follows a naming convention where functions ending in ! mutate their arguments in place — push!(a, x) appends x to the end of a, pop!(a) removes and returns the last element, and append!(a, b) concatenates b's elements onto a, all without allocating a new array. Because arrays are reference types, assigning b = a does not copy the data; both variables point at the same underlying memory, so mutating b with push!(b, 4) also changes what a sees, which is why copy(a) or deepcopy(a) is used when an independent duplicate is actually needed.

🏏

Cricket analogy: push!(a, x) is like adding a name to India's playing XI sheet just before the toss, updated in place; if the coach and captain hold the same physical sheet (b = a), one's edit appears on the other's copy too, so you'd photocopy it (copy(a)) for an independent draft.

Use copy(a) for a shallow copy (nested arrays still share inner references) and deepcopy(a) when you need a fully independent copy of nested mutable structures.

Multi-dimensional Arrays and Memory Layout

Julia stores multi-dimensional arrays in column-major order, meaning that for a matrix A, the elements A[1,1], A[2,1], A[3,1] (an entire first column) are contiguous in memory before A[1,2] begins. This has real performance consequences: looping over columns as the outer loop and rows as the inner loop lets the CPU stream through memory sequentially and take advantage of cache locality, while the opposite loop order jumps around memory and can be dramatically slower on large arrays. Functions like reshape, eachcol, and eachrow let you reinterpret or iterate an array's shape without necessarily copying its underlying data.

🏏

Cricket analogy: Column-major storage is like a scorebook listing all of one batsman's innings across a tournament in a single column before moving to the next batsman — reading down that column stays cache-friendly, while jumping across every batsman's over-1 score zig-zags through the whole book.

Looping over a matrix with the row index as the outer loop and the column index as the inner loop defeats column-major memory locality and can be several times slower than the correct column-outer order — always write for j in axes(A,2), i in axes(A,1) rather than the reverse.

  • Array{T,N} is Julia's parametric container type; Vector = Array{T,1}, Matrix = Array{T,2}.
  • Julia arrays are 1-indexed by default and stored in column-major order.
  • Literal, comprehension, and constructor syntaxes (zeros, ones, rand) all build arrays.
  • Functions ending in ! (push!, pop!, append!) mutate arrays in place without new allocation.
  • Arrays are reference types — assignment shares memory; use copy/deepcopy to duplicate.
  • Loop over columns in the outer loop and rows in the inner loop for cache-friendly performance.
  • Out-of-bounds indexing raises a BoundsError rather than returning garbage or wrapping around.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#JuliaStudyNotes#ArraysInJulia#Arrays#Julia#Creating#Indexing#DataStructures#StudyNotes#SkillVeris