배열 vs List<T> 완벽 비교 분석
Java 배열 vs C# 배열
기본 배열 선언과 초기화:
Java 방식:
// 선언과 초기화
int[] numbers = new int[5];
int[] values = {1, 2, 3, 4, 5};
String[] names = new String[]{"김철수", "이영희"};
// 길이 확인
System.out.println(numbers.length); // 필드 접근
C# 방식:
// 선언과 초기화
int[] numbers = new int[5];
int[] values = {1, 2, 3, 4, 5};
string[] names = {"김철수", "이영희"}; // new string[] 생략 가능
// 길이 확인
Console.WriteLine(numbers.Length); // 프로퍼티 접근 (대문자 L)
List<T> - 동적 배열의 혁신
C#의 List<T>는 Java의 ArrayList<E>와 유사하지만 더 강력한 기능을 제공합니다.
Java ArrayList vs C# List<T> 비교:
| 기능 | Java ArrayList | C# List |
| 선언 | ArrayList<String> list | List<string> list |
| 추가 | list.add("item") | list.Add("item") |
| 삭제 | list.remove("item") | list.Remove("item") |
| 크기 | list.size() | list.Count |
| 인덱스 접근 | list.get(0) | list[0] |
C# List<T> 기본 사용법:
// 리스트 생성과 초기화
List<int> numbers = new List<int>();
List<string> names = new List<string> { "김철수", "이영희", "박민수" };
// 컬렉션 초기화 구문 (C# 3.0+, .NET Framework 4.7.2 지원)
var fruits = new List<string>
{
"사과",
"바나나",
"포도"
};
// 데이터 조작
numbers.Add(10); // 추가
numbers.AddRange(new[] {20, 30, 40}); // 여러 개 추가
numbers.Insert(0, 5); // 특정 위치에 삽입
numbers.Remove(20); // 값으로 삭제
numbers.RemoveAt(0); // 인덱스로 삭제
배열 vs List<T> 선택 가이드
배열을 선택해야 하는 경우:
✅ 고정 크기가 확실할 때
// 요일은 항상 7개
string[] daysOfWeek = {"월", "화", "수", "목", "금", "토", "일"};
// 성적 입력 (학생 수 고정)
int studentCount = 30;
int[] scores = new int[studentCount];
✅ 성능이 극도로 중요할 때
// 대량 데이터 처리 (메모리 효율성)
int[] largeArray = new int[1000000]; // 연속 메모리 할당으로 빠른 접근
// 성능 비교 예시
// 배열: 직접 메모리 접근
// List<T>: 동적 크기 조정 오버헤드 있음
List<T>를 선택해야 하는 경우:
✅ 크기가 동적으로 변할 때 (90% 이상의 경우)
// 사용자 입력을 받아 저장
List<string> userInputs = new List<string>();
while (true)
{
string input = Console.ReadLine();
if (input == "quit") break;
userInputs.Add(input);
}
✅ 편리한 메서드들이 필요할 때
List<int> numbers = new List<int> {5, 2, 8, 1, 9};
// 강력한 내장 메서드들
numbers.Sort(); // 정렬
bool contains = numbers.Contains(5); // 포함 여부
int index = numbers.IndexOf(8); // 인덱스 찾기
numbers.Clear(); // 전체 삭제
foreach문 완전 정복
Java 향상된 for문 vs C# foreach문
Java 향상된 for문:
List<String> names = Arrays.asList("김철수", "이영희", "박민수");
for (String name : names) {
System.out.println(name);
}
C# foreach문:
List<string> names = new List<string> {"김철수", "이영희", "박민수"};
foreach (string name in names) // in 키워드 사용!
{
Console.WriteLine(name);
}
foreach문의 다양한 활용 패턴
배열과 리스트 순회:
// 배열 순회
int[] numbers = {1, 2, 3, 4, 5};
foreach (int num in numbers)
{
Console.WriteLine($"숫자: {num}");
}
// 리스트 순회
List<string> cities = new List<string> {"서울", "부산", "대구"};
foreach (string city in cities)
{
Console.WriteLine($"도시: {city}");
}
인덱스가 필요한 경우의 해결책:
// 방법 1: 전통적인 for문 사용
List<string> items = new List<string> {"A", "B", "C"};
for (int i = 0; i < items.Count; i++)
{
Console.WriteLine($"{i}: {items[i]}");
}
// 방법 2: LINQ의 Select 활용 (고급)
foreach (var item in items.Select((value, index) => new {value, index}))
{
Console.WriteLine($"{item.index}: {item.value}");
}
var 키워드와 foreach의 조합
// 타입이 명확한 복잡한 컬렉션에서 var 활용
var dictionary = new Dictionary<string, List<Employee>>();
foreach (var kvp in dictionary) // KeyValuePair 타입이 명확
{
foreach (var employee in kvp.Value) // List<Employee> 타입이 명확
{
Console.WriteLine($"{kvp.Key}: {employee.Name}");
}
}
LINQ 기초: 데이터 처리의 혁명
LINQ란 무엇인가?
LINQ(Language Integrated Query)는 C# 코드 안에서 SQL처럼 데이터를 조회하고 조작할 수 있는 강력한 기능입니다. Java의 Stream API와 유사하지만 더 직관적입니다.
Java Stream vs C# LINQ 비교:
| 기능 | Java Stream | C# LINQ |
| 필터링 | .filter(x -> x > 5) | .Where(x => x > 5) |
| 변환 | .map(x -> x * 2) | .Select(x => x * 2) |
| 정렬 | .sorted() | .OrderBy(x => x) |
| 집계 | .collect(Collectors.toList()) | .ToList() |
LINQ 기본 문법과 using System.Linq
필수 using 선언:
using System;
using System.Collections.Generic;
using System.Linq; // LINQ 사용을 위해 필수! (.NET Framework 3.5 이상)
namespace MyProgram
{
class Program
{
static void Main()
{
// LINQ 메서드들 사용 가능
}
}
}
기본 LINQ 메서드들:
List<int> numbers = new List<int> {5, 2, 8, 1, 9, 3};
// Where - 조건 필터링
var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();
// 결과: [2, 8]
// OrderBy - 오름차순 정렬
var ascending = numbers.OrderBy(n => n).ToList();
// 결과: [1, 2, 3, 5, 8, 9]
// OrderByDescending - 내림차순 정렬
var descending = numbers.OrderByDescending(n => n).ToList();
// 결과: [9, 8, 5, 3, 2, 1]
// Select - 변환
var doubled = numbers.Select(n => n * 2).ToList();
// 결과: [10, 4, 16, 2, 18, 6]
실무에서 자주 사용하는 LINQ 패턴
문자열 컬렉션 처리:
List<string> names = new List<string>
{
"김철수", "이영희", "박민수", "김영희", "이철수"
};
// 성이 '김'인 사람만 필터링
var kimFamily = names.Where(name => name.StartsWith("김")).ToList();
// 이름 길이 순으로 정렬
var sortedByLength = names.OrderBy(name => name.Length).ToList();
// 모든 이름을 대문자로 변환 (영문 예시)
List<string> englishNames = new List<string> {"john", "mary", "peter"};
var upperNames = englishNames.Select(name => name.ToUpper()).ToList();
복합 객체 처리:
// Person 클래스 정의
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Department { get; set; }
}
List<Person> employees = new List<Person>
{
new Person {Name = "김철수", Age = 30, Department = "개발팀"},
new Person {Name = "이영희", Age = 25, Department = "디자인팀"},
new Person {Name = "박민수", Age = 35, Department = "개발팀"}
};
// 30세 이상인 개발팀 직원
var seniorDevelopers = employees
.Where(emp => emp.Age >= 30 && emp.Department == "개발팀")
.ToList();
// 나이 순으로 정렬
var sortedByAge = employees.OrderBy(emp => emp.Age).ToList();
// 이름만 추출
var nameList = employees.Select(emp => emp.Name).ToList();
메서드 체이닝의 강력함
List<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 여러 LINQ 메서드를 연결
var result = numbers
.Where(n => n % 2 == 0) // 짝수만 필터링
.Select(n => n * n) // 제곱 계산
.OrderByDescending(n => n) // 내림차순 정렬
.ToList(); // 리스트로 변환
// 결과: [100, 64, 36, 16, 4]
Console.WriteLine(string.Join(", ", result));
Visual Studio의 LINQ 자동 완성 마법
using System.Linq 자동 추가 기능
Visual Studio 2019의 똑똑한 도움:
- OrderBy 입력 시 자동 감지
List<int> numbers = new List<int> {3, 1, 4};
var sorted = numbers.OrderBy // ← 여기서 빨간 밑줄
- 전구 아이콘 클릭 또는 Ctrl + .
💡 using System.Linq를 추가하시겠습니까?
- 자동으로 파일 상단에 추가
using System;
using System.Collections.Generic;
using System.Linq; // ← 자동 추가됨!
IntelliSense로 LINQ 메서드 탐색
점(.) 입력 후 나타나는 LINQ 메서드들:
List<string> items = new List<string>();
items. // ← 점 입력 시 IntelliSense 활성화
// 나타나는 주요 LINQ 메서드들:
// - Where
// - Select
// - OrderBy
// - OrderByDescending
// - First
// - FirstOrDefault
// - Any
// - All
// - Count
// - Sum
// - Average
고급 컬렉션 활용 패턴
Dictionary<TKey, TValue> 실무 활용
Java HashMap vs C# Dictionary:
| 기능 | Java HashMap | C# Dictionary |
| 생성 | new HashMap<String, Integer>() | new Dictionary<string, int>() |
| 추가 (덮어쓰기) | map.put(key, value) | dict[key] = value |
| 추가 (새로만) | - | dict.Add(key, value) |
| 조회 | map.get(key) | dict[key] |
| 존재 확인 | map.containsKey(key) | dict.ContainsKey(key) |
실무 Dictionary 패턴:
// 부서별 직원 수 관리
var departmentCount = new Dictionary<string, int>
{
{"개발팀", 15},
{"디자인팀", 8},
{"기획팀", 12}
};
// 안전한 조회 패턴
if (departmentCount.TryGetValue("개발팀", out int count))
{
Console.WriteLine($"개발팀 인원: {count}명");
}
// LINQ와 Dictionary 조합
var largeDepartments = departmentCount
.Where(kvp => kvp.Value > 10)
.Select(kvp => kvp.Key)
.ToList();
실제 업무에서 사용하는 패턴들
데이터 그룹핑:
List<Person> employees = GetEmployees();
// 부서별 그룹핑
var groupedByDept = employees.GroupBy(emp => emp.Department);
foreach (var group in groupedByDept)
{
Console.WriteLine($"{group.Key} 부서:");
foreach (var emp in group)
{
Console.WriteLine($" - {emp.Name}");
}
}
데이터 검증:
List<int> scores = new List<int> {85, 92, 78, 96, 88};
// 모든 점수가 70점 이상인지 확인
bool allPassed = scores.All(score => score >= 70);
// 90점 이상인 점수가 있는지 확인
bool hasExcellent = scores.Any(score => score >= 90);
// 평균 계산
double average = scores.Average();
성능 고려사항과 베스트 프랙티스
ToList() vs IEnumerable
즉시 실행 vs 지연 실행:
List<int> numbers = new List<int> {1, 2, 3, 4, 5};
// 지연 실행 (IEnumerable) - 권장
var query = numbers.Where(n => n > 3);
// 즉시 실행 (List) - 필요한 경우에만
var list = numbers.Where(n => n > 3).ToList();
// 사용 시점에 실행됨
foreach (var num in query) // 여기서 실제 필터링 실행
{
Console.WriteLine(num);
}
언제 ToList()를 사용해야 하나:
✅ 여러 번 반복할 때:
var expensiveQuery = data.Where(x => ComplexOperation(x));
var list = expensiveQuery.ToList(); // 한 번만 계산
// 여러 번 사용
foreach (var item in list) { /* 첫 번째 사용 */ }
foreach (var item in list) { /* 두 번째 사용 */ }
✅ 개수를 확인해야 할 때:
var filtered = data.Where(x => x.IsValid).ToList();
if (filtered.Count > 0) // Count 프로퍼티 사용
{
ProcessData(filtered);
}
정리 및 다음 단계
핵심 요약표
| 개념 | Java | C# | 권장 사용 |
| 동적 배열 | ArrayList<T> | List<T> | ⭐⭐⭐⭐⭐ |
| 반복문 | for (T item : list) | foreach (T item in list) | ⭐⭐⭐⭐⭐ |
| 데이터 처리 | Stream API | LINQ | ⭐⭐⭐⭐⭐ |
| 정렬 | Collections.sort() | .OrderBy() | ⭐⭐⭐⭐ |
| 필터링 | .filter() | .Where() | ⭐⭐⭐⭐⭐ |
학습 체크리스트
- [ ] 배열 vs List<T> 선택 기준 이해
- [ ] foreach문과 in 키워드 숙지
- [ ] using System.Linq 필수성 이해
- [ ] Where, OrderBy, OrderByDescending 활용
- [ ] 메서드 체이닝으로 복합 조건 처리
- [ ] Dictionary<TKey, TValue> 기본 사용법
- [ ] ToList() vs IEnumerable 성능 차이 파악
버전 호환성 정보
| 기능 | .NET Framework 4.7.2 | 최신 .NET 6/7/8 |
| LINQ | ✅ 완전 지원 | ✅ 완전 지원 |
| 컬렉션 초기화 | ✅ 완전 지원 | ✅ 완전 지원 |
| var 키워드 | ✅ 완전 지원 | ✅ 완전 지원 |
| 람다 표현식 | ✅ 완전 지원 | ✅ 완전 지원 |