To append to an array in PowerShell, use the += operator. It adds the new item to the end, so a list of two servers becomes three:
$servers = 'WEB01', 'WEB02'
$servers += 'SQL01'
$servers -join ', '
"Count: $($servers.Count)"
Output:
WEB01, WEB02, SQL01
Count: 3
That’s all you need for small scripts. But += doesn’t really grow the array. It builds a brand-new one each time, which explains most of the surprises below.
I ran each example in PowerShell 7.6 and Windows PowerShell 5.1. The results matched, apart from the speed test, where the two versions are very different.
Add multiple values to an array
Put several values after +=, separated by commas, or add another array. Either way, each value becomes its own item:
$servers = 'WEB01', 'WEB02'
$servers += 'SQL01', 'SQL02'
$newSite = 'APP01', 'APP02'
$servers += $newSite
$servers -join ', '
Output:
WEB01, WEB02, SQL01, SQL02, APP01, APP02
If you want the second array stored as a single item instead, put a comma in front of it. That’s the unary comma operator:
$groups = @('Admins')
$groups += , ('Sales', 'Support')
"Count: $($groups.Count)"
"Last item: $($groups[-1] -join ' + ')"
Output:
Count: 2
Last item: Sales + Support
Create an empty array and add items
Start with @() and add to it with +=:
$servers = @()
"Starting count: $($servers.Count)"
$servers += 'WEB01'
"After adding: $($servers.Count)"
Output:
Starting count: 0
After adding: 1
Don’t try .Add() on a normal array. PowerShell arrays have a fixed size, so the method throws an error:
$servers = 'WEB01', 'WEB02'
try {
$servers.Add('SQL01')
}
catch {
$_.Exception.InnerException.Message
}
Output:
Collection was of a fixed size.
If you need .Add(), use a list instead, as shown further down.
Add an item to the beginning of an array
Put the new item in its own array first and add the old array after it. Leaving out the @() is a common mistake:
$cities = 'Chicago', 'Houston'
$wrong = 'New York' + $cities
"Without @(): $wrong"
$cities = @('New York') + $cities
"With @(): $($cities -join ', ')"
Output:
Without @(): New YorkChicago Houston
With @(): New York, Chicago, Houston
Without @(), PowerShell sees a string on the left, so it joins everything into one string. The left side decides what + does.
Use a List when the array changes a lot
A generic List can grow in place. It has methods for adding, inserting and removing, which a plain array doesn’t:
$servers = [System.Collections.Generic.List[string]]::new()
$servers.Add('WEB01')
$servers.AddRange([string[]]('WEB02', 'SQL01'))
$servers.Insert(0, 'DC01')
$null = $servers.Remove('WEB02')
$servers -join ', '
Output:
DC01, WEB01, SQL01
Insert(0, ...) is the cleanest way to add to the front. Remove() returns true or false, so I send that to $null.
Why ArrayList prints numbers
You’ll see System.Collections.ArrayList in older scripts. Its Add() method returns the new item’s index, and PowerShell prints it:
$list = [System.Collections.ArrayList]::new()
$list.Add('WEB01')
$list.Add('WEB02')
[void]$list.Add('SQL01')
"Items: $($list -join ', ')"
Output:
0
1
Items: WEB01, WEB02, SQL01
Cast the call to [void] to hide the number. Or better, use List[string], which doesn’t return anything.
Is += slow in PowerShell?
It used to be very slow, and it still is in Windows PowerShell 5.1. I timed three ways of building a 10,000-item array on the same PC:
$count = 10000
$plus = Measure-Command {
$result = @()
foreach ($i in 1..$count) { $result += $i }
}
$list = Measure-Command {
$result = [System.Collections.Generic.List[int]]::new()
foreach ($i in 1..$count) { $result.Add($i) }
}
$direct = Measure-Command {
$result = foreach ($i in 1..$count) { $i }
}
'+= operator: {0,7:N0} ms' -f $plus.TotalMilliseconds
'List.Add(): {0,7:N0} ms' -f $list.TotalMilliseconds
'Loop assignment: {0,7:N0} ms' -f $direct.TotalMilliseconds
Output in PowerShell 7.6:
+= operator: 53 ms
List.Add(): 130 ms
Loop assignment: 6 ms

In 5.1, += took well over a second, because it copies the whole array on every loop. PowerShell 7.5 made += much faster, so 7.6 did it in 53 ms.
The winner in both versions is to let the loop build the array for you. Assign the whole foreach to a variable, and every value it outputs is collected:
$results = foreach ($server in 'WEB01', 'WEB02', 'SQL01') {
"$server checked"
}
"Collected $($results.Count) results: $($results -join '; ')"
Output:
Collected 3 results: WEB01 checked; WEB02 checked; SQL01 checked
Microsoft describes the 7.5 change, with its own timings, in What’s New in PowerShell 7.5.
How do I add only unique values to an array?
Check the array with -notcontains before you add. It ignores case, so “chicago” counts as a duplicate of “Chicago”:
$cities = 'New York', 'Chicago'
foreach ($city in 'Houston', 'chicago', 'Phoenix') {
if ($cities -notcontains $city) {
$cities += $city
}
}
$cities -join ', '
Output:
New York, Chicago, Houston, Phoenix
Watch the parentheses with -not
A version you’ll find online is if (-not $cities -contains $city). It never adds anything, because -not runs first, on the array:
$cities = 'New York', 'Chicago'
$city = 'Houston'
if (-not $cities -contains $city) { "Added $city" } else { "Skipped $city" }
if (-not ($cities -contains $city)) { "Added $city" } else { "Skipped $city" }
Output:
Skipped Houston
Added Houston

Wrap the test in parentheses, or just use -notcontains, which avoids the problem entirely.
A HashSet for large lists
For thousands of values, a HashSet is faster, and its Add() tells you whether the value was new. Pass OrdinalIgnoreCase, because a HashSet is case-sensitive by default:
$comparer = [System.StringComparer]::OrdinalIgnoreCase
$cities = [System.Collections.Generic.HashSet[string]]::new($comparer)
foreach ($city in 'Houston', 'Chicago', 'houston', 'Phoenix') {
if ($cities.Add($city)) { "Added $city" } else { "Skipped $city (already there)" }
}
Output:
Added Houston
Added Chicago
Skipped houston (already there)
Added Phoenix
Add to an array inside a function
This one catches a lot of people. Using += inside a function creates a new array there, so the caller’s array doesn’t change:
function Add-Server {
param($List, $Name)
$List += $Name
"Inside the function: $($List.Count) servers"
}
$servers = @('WEB01', 'WEB02')
Add-Server -List $servers -Name 'SQL01'
"Back in the script: $($servers.Count) servers"
Output:
Inside the function: 3 servers
Back in the script: 2 servers

Either return the new array and assign it in the script, or pass a List. The function then adds to the same list the caller has:
function Add-Server {
param([System.Collections.Generic.List[string]]$List, [string]$Name)
$List.Add($Name)
}
$servers = [System.Collections.Generic.List[string]]::new()
$servers.Add('WEB01')
Add-Server -List $servers -Name 'SQL01'
"Back in the script: $($servers -join ', ')"
Output:
Back in the script: WEB01, SQL01
Frequently Asked Questions
How do I append to an array in PowerShell?
Use $array += 'NewItem'. It creates a new array with the item added to the end. For many additions, use a generic List or collect a loop’s output instead.
Why can’t I use .Add() on a PowerShell array?
Arrays have a fixed size, so .Add() throws “Collection was of a fixed size.” Use +=, or create a [System.Collections.Generic.List[string]].
How do I add an item to the start of an array?
Use $array = @('NewItem') + $array. Without the @(), PowerShell joins everything into a single string.
Is += slow in PowerShell?
In Windows PowerShell 5.1, yes, because it copies the array every time. PowerShell 7.5 and later made it much faster. Assigning a loop’s output to a variable is fastest in both.
Why doesn’t my function change the array I passed in?
+= inside the function creates a new local array. Return it and assign the result, or pass a List and call its Add() method.
Next, try one of these array guides:
- Check if an array contains a value
- Remove items from an array
- Remove duplicates from an array
- Create an empty array
Bijay Kumar is an esteemed author and the mind behind PowerShellFAQs.com, where he shares his extensive knowledge and expertise in PowerShell, with a particular focus on SharePoint projects. Recognized for his contributions to the tech community, Bijay has been honored with the prestigious Microsoft MVP award. With over 15 years of experience in the software industry, he has a rich professional background, having worked with industry giants such as HP and TCS. His insights and guidance have made him a respected figure in the world of software development and administration. Read more.