Ignoring how it is obsoleted the reason I don't recommend ArrayList is because the Add method outputs the index. This means you need to discard the output everytime you do $list.Add() which gets annoying quickly. The List type has a void Add() method so you don't have to worry about that. Aside from that I usually avoid an ArrayList or List and just capture the output into a var and have powershell deal with it all $list = foreach (bar) { "Test-$foo" } The main reason I use a List is when I need to add values to multiple lists in the same loop so I can no longer rely on the output stream. Answer from jborean93 on reddit.com
๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ has arraylist been deprecated?
r/PowerShell on Reddit: has ArrayList been deprecated?
November 23, 2016 -

howdy y'all,

i vaguely recall seeing a post in this subreddit some time back that said the ArrayList had been deprecated. now i can't find it. [blush] the only things that show up on a net search are a couple of posts aimed at C# from several years ago.

so, am i misremembering things again?

take care,
lee


-ps
found the reason ... but i don't really understand it. lookee ...
ArrayList vs List<> in C# - Stack Overflow

  • http://stackoverflow.com/questions/2309694/arraylist-vs-list-in-c-sharp
    lee-

๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ arraylist obsoletion -- do we care?
r/PowerShell on Reddit: ArrayList obsoletion -- do we care?
July 25, 2024 -

I'm fully aware that ArrayList is not recommended for new development. That being said, do you still use it when you are writing PowerShell? I wish I could add a Poll to solicit the responses more easily, but Poll option is greyed out.

I've been roasted for using it before, but it's just so much more familiar and convenient to instantiate, for me.

[System.Collections.ArrayList]$list = @()

Slim and sexy, concise, looks like other PS syntax I'm used to.

[System.Collections.Generic.List[object]]::new()

Newfangled, unwieldy, uses C# constructor, ugly. Requires me to think about what types I'll have in my list. Smug.

(Obviously I'm feeling a little silly here / tongue in cheek, but I really do feel like I just don't want to bother getting used to the new way.)

EDIT: Some of the advice is helpful, but mostly what I was hoping to find out was whether I'm alone or whether you all use ArrayList. It's kind of like, I know I'm supposed to drink 8 glasses of water today, but I have a suspicion that few people actually do. So that's why I'm asking.

FINAL EDIT: After seeing that most people don't use ArrayLists anymore, I think I'm going to learn Lists and do things properly. Turns out I'm in the minority, at least on this sub. Thanks for the discussion everyone.

๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ when to use array vs array list vs list
r/PowerShell on Reddit: When to use array vs array list vs list
April 25, 2022 - Array: When you don't need to dynamically add items to a collection outside a loop. ArrayList: Never. Generic list: When you do need to dynamically add items to a collection outside a loop.
๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ arraylist is adding a list of numbers before my data
r/PowerShell on Reddit: Arraylist is adding a list of numbers before my data
October 16, 2024 -

I am working with Cisco DNA Center (DNAC) to get a list of Network Devices and then pick out just the relevant data. I am able to get the full list of data from DNAC and I am testing creating a new arraylist with the 4 fields that I want from there. I am using $newlist = Testing -allnads $newinfo where $newinfo is the array of PSCustomObjects that I have gotten from DNAC.

Function Testing{
param($allnads) 
$paredlist = New-Object System.Collections.ArrayList 
foreach($device in $allnads){ 
$pareddown = @($device.hostname, $device.managementIpAddress, $device.id, $device.softwareversion) 
$paredlist.add($pareddown)
}
return $paredlist 
}

$newinfo.count is 923 but then $paredlist.count is 1846
The first 923 indexes are all just the index value.
$newlist[0] is 0, $newlist[1] is 1, etc
$newlist[923] gives me the hostname, IP, GUID, and software version of the first switch which I would have expected at index 0.

Is there something stupid I am doing here (probably the case) or some bit of wizardry I need to know about before I just start any iterations through this data with

$i = $newlist.count/2
if($i -lt $newlist.count){... $i +=1}
Top answer
1 of 2
4
I can't see your code, but If you are using ArrayList then the add() method will return the position of the new item. Best fix is to instead use the List type from the generics namespace. List does not return anything on add. ie: $List = [System.Collections.Generic.List[psobject]]::new() # $List.Add($object) # won't output anything. You can also strongly type the list by putting the type where i put psobject here.
2 of 2
3
As mentioned already you can use a generic list instead of an arraylist, but an even better option is to just assign the result of the foreach expression: Function Testing { param($allnads) $paredlist = foreach($device in $allnads) { @($device.hostname, $device.managementIpAddress, $device.id, $device.softwareversion) } return $paredlist } however returning a collection like this kinda goes against the PowerShell pipeline principles. Instead you should be writing the objects one by one to the pipeline so downstream commands can start processing the data immediately. For example if I only want the first X results then I could do Testing | Select-Object -First 10 and your function could stop after the first 10 items instead of having to process all the items just to end up throwing everything past the first 10 results away. This is how you would do that: Function Testing { param($allnads) foreach($device in $allnads) { @($device.hostname, $device.managementIpAddress, $device.id, $device.softwareversion) } } One last important detail here is that PowerShell will automatically unroll collections for you but since you are intentionally creating an array with @() and you presumably don't want it unwrapped by PowerShell you need to prefix it with a comma like this: ,@($device.hostname, $device.managementIpAddress, $device.id, $device.softwareversion).
๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ replace [system.collections.arraylist] with something thread-safe
r/PowerShell on Reddit: Replace [System.Collections.ArrayList] with something thread-safe
May 14, 2024 -

Hi.

I writing scripts that involve multiple API and due to the sequential nature of the single-threaded approach, some take a lot of time to execute.

For a long time I used ArrayList and "+=" approach to create list of arrays but it seems that it's deprecated and not really a best practice. See LINK1 and LINK2.

So, until now, I used approach from LINK1: declare empty ArrayList, looped through the results of my API call with foreach and then added entries with +=.

Of course, it doesn't work with Foreach-Object -Parallel, because ArrayList isn't thread safe.

I tried using ConcurrentBag but I can't access my items like I did in the past.

I.e., if I declare:

$devices = [System.Collections.Concurrent.ConcurrentBag[PSObject]]::new()

I'd like to be able to:

  • $devices[0] - select the first device from the list

  • $devices | Where-Object {$_.SerialNumber -eq "ABC1234567890"}

Doing any of these returns all the results.

Is there any other structure, similar to ArrayList or am I doing something wrong here?

๐ŸŒ
Reddit
reddit.com โ€บ r โ€บ PowerShell โ€บ comments โ€บ b3ehfk โ€บ arrays_vs_arraylists_inboxrules_mailboxpermission
r/PowerShell - Arrays vs ArrayLists, InboxRules & MailboxPermission
March 20, 2019 -

I'm trying to optimize a reporting script, and the biggest win is by using ArrayList instead of @() (other sections have gone from minutes to milliseconds) so I am trying to do the same here. But it doesn't work given the output from each query can be 0..n

Write-Host "STEP 7 " + $StopWatch.ElapsedMilliseconds
<# New arrays #>

$UserInboxRules = @()
$UserDelegates = @()
<#
$UserInboxRules = New-Object System.Collections.ArrayList
$UserDelegates = New-Object System.Collections.ArrayList
#>

Write-Host "STEP 8 " + $StopWatch.ElapsedMilliseconds
<# Build UserInboxRules and UserDelegates tables #>
ForEach ($entry in $MbxDb) {
$UserInboxRules += Get-InboxRule -Mailbox $entry.Email | Select-Object Name, Description, Enabled, Priority, ForwardTo, ForwardAsAttachmentTo, RedirectTo, DeleteMessage | Where-Object {($_.ForwardTo -ne $null) -or ($_.ForwardAsAttachmentTo -ne $null) -or ($_.RedirectsTo -ne $null)}
$UserDelegates += Get-MailboxPermission -Identity $entry.Email | Where-Object {($_.IsInherited -ne "True") -and ($_.User -notlike "*SELF*")}

<#
$UserInboxRulesEntry = Get-InboxRule -Mailbox $entry.Email | Select-Object Name, Description, Enabled, Priority, ForwardTo, ForwardAsAttachmentTo, RedirectTo, DeleteMessage | Where-Object {($_.ForwardTo -ne $null) -or ($_.ForwardAsAttachmentTo -ne $null) -or ($_.RedirectsTo -ne $null)}
$UserDelegatesEntry = Get-MailboxPermission -Identity $entry.Email | Where-Object {($_.IsInherited -ne "True") -and ($_.User -notlike "*SELF*")}
[void]$UserInboxRules.Add($UserInboxRulesEntry)
[void]$UserDelegates.Add($UserDelegatesEntry)
#>
}
Write-Host "STEP 9 " + $StopWatch.ElapsedMilliseconds

Any thoughts?

Edit: Formatted.

Top answer
1 of 4
3

Howdy,

If I understand the problem correctly:

Each foreach loop query may return more than one object. When using the standard array with += it adds each object as a separate item. But when using the add method on the arraylist it is instead creating a jagged array inside of the arraylist (ie - instead of adding each object from the query separately, it is instead adding them all as a complete array for each loop)?

If so, have you tried using the arraylist addrange method instead?

edit: I just tested this and realized that if your result is a single item the addrange method will fail. I guess you could add some logic to test your results of the query with a if/elseif. If the result is a single object, use the add method. Elseif use the addrange method. Or maybe I just completely misunderstood the problem.... :-)

2 of 4
3

howdy PedroAsani,

as others have pointed out, += is NOT the thing to use with an arraylist. [grin] on my win7ps5.1 system that will convert the arraylist to a standard array ... and slow things down quite a bit.

plus, arraylists are both deprecated AND rather annoying - all those [voids] to suppress unwanted "i added something!" msgs.

so, you are recommended to use a generic.list - and that does NOT generate the silly "added something" stuff. [grin]

however, if you are not going to change the size of the array very often, then feeding the loop [foreach, ForEach-Object, While, any pipeline output, or any other loop] directly to a $Var is the fastest. lookee ...

$RepeatCount = 1e4'Direct from Foreach    = {0,10:N3} milliseconds' -f (Measure-Command -Expression {    $DFF_Result = foreach ($Item in 1..$RepeatCount)        {        $Item        }    }).TotalMilliseconds'Array add              = {0,10:N3} milliseconds' -f (Measure-Command -Expression {    $Ar_Result = @()    foreach ($Item in 1..$RepeatCount)        {        $Ar_Result += $Item        }    }).TotalMilliseconds'ArrayList add          = {0,10:N3} milliseconds' -f (Measure-Command -Expression {    $AL_Result = [System.Collections.ArrayList]::new()    foreach ($Item in 1..$RepeatCount)        {        $Null = $AL_Result.Add($Item)        }    }).TotalMilliseconds'Generic.List add       = {0,10:N3} milliseconds' -f (Measure-Command -Expression {    $GL_Result = [System.Collections.Generic.List[int]]::new()    foreach ($Item in 1..$RepeatCount)        {        $GL_Result.Add($Item)        }    }).TotalMilliseconds

output ...

Direct from Foreach    =     23.432 millisecondsArray add              =  3,831.392 millisecondsArrayList add          =     31.171 millisecondsGeneric.List add       =     34.799 milliseconds

hope that helps,lee

๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ is there an easy and elegant way of removing the last element of an array?
r/PowerShell on Reddit: Is there an easy and elegant way of removing the last element of an array?
January 14, 2025 -

Edit: Solved

It's much more flexible to use generic lists instead of arrays. Arrays are immutable and should not be used when there is a need to add or remove elements. Another option is to use array lists, but others reported that they are deprecated and that generic lists should be used instead.

Thank you all for the help!

-------------

PowerShell 7, an array like $array = @()

Like the title say - is there?

The solutions I've found online are all wrong.

- Array slicing

$array = $array[0..($array.Length - 2)]

This does not work if the array length is 1, because it resolves to $array[0..-1]. Step-by-step debugging shows that instead of deleting the last remaining element of the array, it will duplicate that element. The result will be an array of 2 elements, not 0.

- Select-Object

$array = $array | Select-Object -SkipLast 1

This does not work well with Hashtables as array elements. If your array elements are Hashtables, it will convert them to System.Collections.Hashtable. Hashtable ($example = @{}) and System.Collection.Hashtable are not the same type and operations on those two types are different (with different results).

Edit for the above: There was a typo in that part of my code and it returned some nonsense results. My bad.

- System.Collections.ArrayList

Yes, you can convert an array to System.Collection.ArrayList, but you are then working with System.Collections.ArrayList, not with an array ($array = @()).

----------------

One solution to all of this is to ask if the array length is greater than one, and handle arrays of 1 and 0 elements separately. It's using an if statement to simply remove the last element of an array, which is really bad.

Another solution is to loop through an array manually and create a new one while excluding the last element.

And the last solution that I've found is not to use arrays at all and use generic lists or array lists instead.

Is one of these options really the only solution or is there something that I'm missing?

Find elsewhere
๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ adding to array, won't add new item to new index!!
r/PowerShell on Reddit: Adding to Array, won't add new item to new index!!
April 21, 2020 -

Code: https://pastebin.com/VQQUFJEM

Hey,

Im having issues where, the new value received in the loop is not being added to a new index in the ArrayList.

When I print out the value of the ArrayList, all the items are added into one index, like a string.

๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ two ways of creating a new system.collections.arraylist object, what's the difference?
r/PowerShell on Reddit: Two ways of creating a new System.Collections.ArrayList object, what's the difference?
April 7, 2023 -

I've come across two ways of creating a new System.Collections.ArrayList object:

$arrA = New-Object System.Collections.ArrayList
$arrB = [System.Collections.ArrayList]@() 

I have two questions:

  1. for arrB, if I'm reading this right, @() is creating an empty array and then it's being cast into [System.Collections.ArrayList]?

  2. Working with the created object is the same for me either way, but are there any differences I may be missing?

I made a quick test and casting was faster, but the difference is only noticeable when creating new arrays reaches the hundreds of thousands to millions (tested on an old A10-7870k). Doesn't really matter when I'm creating one array, but I thought it was mildly interesting.

$max = 100000
$ticksStart = (Get-Date).Ticks
for ($i = 0; $i -lt $max; $i++)
{
	$arrA = New-Object System.Collections.ArrayList
}
$ticksEnd = (Get-Date).Ticks
Write-Host 'arrA (ticks)	: ' ($ticksEnd - $ticksStart)

$ticksStart = (Get-Date).Ticks
for ($i = 0; $i -lt $max; $i++)
{
	$arrB = [System.Collections.ArrayList]@()
}
$ticksEnd = (Get-Date).Ticks
Write-Host  'arrB (ticks)	: ' ($ticksEnd - $ticksStart)
arrA (ticks)	:  64310000
arrB (ticks)	:  3170000
๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ arraylist in $body = @"... in one line, instead of 2
r/PowerShell on Reddit: Arraylist in $body = @"... in one line, instead of 2
January 26, 2023 -

I have following problem.

I have an arraylist. This arraylist consists of 2 Entries

User1User2

However, If I use this arraylist within a $body=@"..."@ the arraylist is reduced to 1 line.

I want the $ararylist to be 2 lines (for this example), not 1 line.

Code Example is attached to show what I mean.

The $Arraylist within $body should be the same as outside the $body. (meaning adding 2 lines to the $body.

$Parameters = "User1","User2"
$Arraylist = New-Object System.Collections.ArrayList  
$i = 1
Foreach ($Parameter in $Parameters){
    $Line = "String"+$i+" =" + $Parameter
    $Arraylist.Add($Line) | Out-Null
    $i++ 
}
$Body = @"

Body begins here
string0 = Bla

Arraylist in 1 line instead of 2 
 $Arraylist
"@
$Arraylist
$body

output of $Body is:

Body begins here

string0 = Bla

Arraylist in 1 line instead of 2

String1 =User1 String2 =User2

Output should be:

Body begins here

string0 = Bla

Arraylist in 1 line instead of 2

String1 =User1

String2 =User2

Any help is appreciated.

๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ why is += so frowned upon?
r/PowerShell on Reddit: Why is += so frowned upon?
April 20, 2021 -

Let's say I loop through a collection of computers, retrieve some information here and there, create a hastable out of that information and add it to an array.

$file = Get-Content $pathtofile
$output = @()
[PSCustomObject]$h = @{}
foreach ($item in $file){
    $h."Name" = $item
    ...other properties...
    $output += $h
}

I understand that adding to an array this way will destroy the array upon each iteration to create it anew. I understand that when dealing with very large amounts of data, it can lead to longer processing times.

But aside from that, why is it a bad idea? I've never had errors come out of using this (using PS 5.1), and always found it handy. But I feel like there's something i'm missing...

Today I was messing around with arrays, arraylists, and generic lists. I'm also curious to know more about their advantages and inconvients, which I find closely related to using += or methods.

Top answer
1 of 16
86
This is not a PowerShell problem, this is a general issue with arrays (at a Computer Science and Data Structure level). An array, by definition is fixed length. it does this by allocating the array in memory when defined. Arrays have minimal overhead which makes them fast, but it also requires them to be in contiguous memory space. When you add a new item to an array, it creates a new array with space for one more item, then it copies the values from the old array and adds in your new value. Finally, it destroys the old array. If you are looping through something and it adds an item with each iteration, then youโ€™re creating a new array with each iteration and destroying the previous one... like the teleportation problem... BUT WORSE! ๐Ÿ˜ณ A list works differently by holding extra data with each item that points where the next item is in memory. This means that lists donโ€™t need to be in a contiguous memory space as the last item can be updated with the pointer to the new item you add. Some lists even store extra info to point to the previous item so you can traverse the list in either direction. It just depends what is better in the situation: a fixed array that is low overhead but immutable, or a flexible list with extra overhead?
2 of 16
61
Sounds like you already know, it works well enough for small things, but the .add() syntax is just a little more straight forward once you get used to creating the arraylists and is a LOT faster on big data sets. One of the things most people pick up in coding is that you start to develop habits based on times you had problems in the past. Nearly anyone with any saddle time in powershell has written a script that worked fine in testing and ended up swallowing all their ram, and ran slow as hell when they took it to do a real workload. Then they learned the arraylist syntax and everything ran 10x faster so they just get into the habit of always using the faster syntax.
๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ powershell array and arraylist - storing multiple items as a one variable
r/PowerShell on Reddit: PowerShell Array and ArrayList - storing multiple items as a one variable
August 24, 2021 - PowerShell includes a command-line shell, object-oriented scripting language, and a set of tools for executing scripts/cmdlets and managing modules. ... ArrayList is a deprecated .NET 1.1 feature....
๐ŸŒ
Reddit
reddit.com โ€บ r/powershell โ€บ please help me fix my incredibly messy reporting method!
r/PowerShell on Reddit: Please help me fix my incredibly messy reporting method!
January 19, 2024 -

I have a script that look at our Azure AD environment and pulls out any expiring certificates or secrets and puts them into an array which is exported as a csv at the end for reporting purposes. Because each application can have multiple secrets/certificates, the way I'm currently doing this is to have nested for each loops (one for Applications, and then separate loops within the ForEach Application loop looking at each certificate and secret), and inside each loop, recreate the whole record for the application just to add the expiring secret/certificate to the array I'm using to create the report (since every record in the array has to contain all the same properties as other records, I have to add the certificate start date even if I'm looking only at client secrets etc.).

This is just incredibly messy and inefficient and I'm wondering if there's a better way to do this that doesn't mean having to recreate the entire array in every different loop.

For example:

                $Log = New-Object System.Object

            $Log | Add-Member -MemberType NoteProperty -Name "ApplicationName" -Value $AppName
            $Log | Add-Member -MemberType NoteProperty -Name "ApplicationID" -Value $ApplID
            $Log | Add-Member -MemberType NoteProperty -Name "Secret Start Date" -Value $null
            $Log | Add-Member -MemberType NoteProperty -Name "Secret End Date" -value $null
            $Log | Add-Member -MemberType NoteProperty -Name "Certificate Start Date" -Value $CStartDate
            $Log | Add-Member -MemberType NoteProperty -Name "Certificate End Date" -value $CEndDate
            $Log | Add-Member -MemberType NoteProperty -Name "SAML Certificate Start Date" -Value $null
            $Log | Add-Member -MemberType NoteProperty -Name "SAML Certificate End Date" -value $null
            $Log | Add-Member -MemberType NoteProperty -Name "Owner" -Value $Username
            $Log | Add-Member -MemberType NoteProperty -Name "Owner_ObjectID" -value $OwnerID

            $Logs += $Log  

Currently this block of code is copy/pasted 5 separate times in my script, just with different values nulled out depending on what that loop is looking at. The only other way I could think to do this would be to put all the expiring secrets/certificates for each application in their own array, and then just generate the record in the application loop with those arrays as the values for the start/end dates for the certs/secrets, rather than having a separate record for each certificate and each secret etc, but I'm open to hearing any suggestions!
Thanks

Top answer
1 of 4
3

Simplifying your script can make it more efficient.

# Define a function to create an application log object
function New-ApplicationLog {
    param (
        [string]$AppName,
        [string]$ApplID,
        [DateTime]$CStartDate,
        [DateTime]$CEndDate,
        [string]$Username,
        [string]$OwnerID
    )

    $log = New-Object PSObject -Property @{
        ApplicationName = $AppName
        ApplicationID = $ApplID
        SecretStartDate = $null
        SecretEndDate = $null
        CertificateStartDate = $CStartDate
        CertificateEndDate = $CEndDate
        SAMLStartDate = $null
        SAMLEndDate = $null
        Owner = $Username
        Owner_ObjectID = $OwnerID
    }

    return $log
}

# Initialize an array to store application logs
$Logs = @()

# Example usage within your loop
foreach ($Application in $Applications) {
    # Retrieve necessary information for the application
    $AppName = $Application.Name
    $ApplID = $Application.ID
    $CStartDate = $Application.CertificateStartDate
    $CEndDate = $Application.CertificateEndDate
    $Username = $Application.Owner
    $OwnerID = $Application.OwnerID

    # Create an application log object
    $Log = New-ApplicationLog -AppName $AppName -ApplID $ApplID -CStartDate $CStartDate -CEndDate $CEndDate -Username $Username -OwnerID $OwnerID

    # Add the log object to the array
    $Logs += $Log
}

# Export the array to a CSV file
$Logs | Export-Csv -Path "Path\To\Your\Report.csv" -NoTypeInformation

hopefully this helps you!

2 of 4
3

There are various ways to deal with this

To start, use ArrayLists, not Arrays.

Second, have some code I wrote on the fly.

## first two elements are outside the various loops and repetitions

# this will contain the various logs. Longer, easier-to-read name
$LogList = [System.Collections.ArrayList]::new()

# this is the template of your logs.
# as Hashtable so it gets cloned, not linked, to the various iterations
$LogTemplate = [hashtable]@{
    'ApplicationName'             = $null
    'ApplicationID'               = $null
    'Secret Start Date'           = $null
    'Secret End Date'             = $null
    'Certificate Start Date'      = $null
    'Certificate End Date'        = $null
    'SAML Certificate Start Date' = $null
    'SAML Certificate End Date'   = $null
    'Owner'                       = $null
    'Owner_ObjectID'              = $null
}
##

## This part will be in the various repetitions

# copy the template as a PSCustomObject
$logSingle = [pscustomobject]$LogTemplate

# Modify ONLY the values you need.
# Everything else will stay at $null value
$LogSingle.ApplicationID = 1

# add the log to the list
# [ArrayLisy].Add() returns the index position of the added item.
# There are a number of easy workaround if that's a problem.
$LogList.add($LogSingle)
##


## outside the repetitions
# here you have your ArrayList, ready to be converted to CSV, directly exported, or whatever you want
$LogList
๐ŸŒ
| How
pipe.how โ€บ new-arraylist
PowerShell Collections: ArrayList | How
January 17, 2020 - This post will look at the first alternative to arrays that one usually encounters: ArrayList. A disclaimer before diving into the ArrayList, however, is that it is deprecated and the recommendation from Microsoft is that it should not be used for any new development.