자바 for 와 foreach 에 대해 효율 과 안전 을 동시에 고려 합 니 다.
배열 에 대한 접근 은 for 방식 을 사용 해 야 합 니 다. 성능 이 더 높 기 때 문 입 니 다.아래 코드 는 적절 하 다.
Object[] objArray = ...;
int objArrayLength = objArray.Length;
for (int i = 0; i < objArrayLength; ++i)
{
// do something ...
}
String str = ...;
int strLength = str.Length;
for (int i = 0; i < strLength; ++i)
{
// do something ...
}
ArrayList 와 같은 아래 표 시 를 사용 하여 무 작위 로 접근 할 수 있 는 데이터 구 조 는 아래 표 시 를 사용 하여 접근 합 니 다. foreach 방식 보다 순서 적 으로 접근 하고 속도 가 빠 릅 니 다.foreach 이렇게 쓰 면 사용 하 는 과정 에서 추가 대상 인 Enumerator 가 생 성 되 고 방문 할 때마다 더 많은 조작 이 필요 하 며 성능 이 떨 어 집 니 다.다음 두 가지 쓰기 로 컴 파일 된 코드 는 같 습 니 다.
第一种写法:
IList list = new ArrayList();
IEnumerator iter = list.GetEnumerator();
try
{
while (iter.MoveNext())
{
Object obj = iter.Current;
//do something ...
}
}
finally
{
IDisposable disposableObj = iter as IDisposable;
if (disposableObj != null)
{
disposableObj.Dispose();
}
}
第二种写法:
IList list = new ArrayList();
foreach (Object obj in list)
{
//do something ...
}
이 두 가지 표기 법 에 비해 첫 번 째 표기 법 은 매우 수 다스 러 워 서 C\# foreach 의 문법 을 도입 했다.첫 번 째 쓰기 관찰 을 통 해 foreach 는 GetEnumerator 를 통 해 IEnumerator 대상 을 얻 고 IEnumerator 대상 을 통 해 MoveNext () 방법 을 실행 하고 Current 속성 을 가 져 와 옮 겨 다 닙 니 다.
저 희 는 Reflector 도 구 를 통 해 mscorlib. dll 에서 System. collection. Array List 의 실현 을 확인 합 니 다.
//간단하게 보기 위해 서 저 는 Array List 의 Add, Clear, GetEnumerator 코드 만 보 여 줍 니 다.
public class ArrayList
{
//这是一个版本标识,ArrayList对象,每做一个修改操作,_version都会加1
private int _version;
public virtual int Add(object value)
{
int num1;
if (this._size == this._items.Length)
{
this.EnsureCapacity((this._size + 1));
}
this._items[this._size] = value;
++this._version; //注意此处
this._size = ((num1 = this._size) + 1);
return num1;
}
public virtual void Clear()
{
Array.Clear(this._items, 0, this._size);
this._size = 0;
++this._version; //注意此处
}
//每次调用GetEnumerator方法,都会构造一个FastArrayListEnumerator
//或者ArrayListEnumeratorSimple对象。
public virtual IEnumerator GetEnumerator()
{
if (base.GetType() == typeof(ArrayList))
{
return new ArrayList.FastArrayListEnumerator(this);
}
return new ArrayList.ArrayListEnumeratorSimple(this);
}
}
위 코드 를 통 해 알 수 있 듯 이 Array List 는version 구성원 변 수 를 버 전 표지 로 하 는 경우 Add, Clear 등 Array List 내용 을 수정 하 는 작업 을 수행 할 때마다 버 전 번 호 를 1 로 추가 하고 GetEnumerator 방법 을 호출 할 때마다 FastArray ListEnumerator 나 Array ListEnumerator Simple 대상 을 구성 합 니 다.우리 다시 보 자.
FastArrayListEnumerator的实现:
class FastArrayListEnumerator
{
private int version;
internal FastArrayListEnumerator(ArrayList list)
{
this.list = list;
this.index = -1;
//获取构建FastArrayListEnumerator对象时ArrayList的版本号
this.version = list._version;
this.lastIndex = (list._size - 1);
}
public bool MoveNext()
{
int num1;
//比较ArrayList当前的版本号,
//是否和构建FastArrayListEnumerator对象时的版本号一致
//如果不一致,则抛出异常。
if (this.version != this.list._version)
{
throw new InvalidOperationException(
Environment.GetResourceString("InvalidOperation_EnumFailedVersion")
);
}
//... ...
}
}
FastArray List Enumerator 대상 이 구축 되 었 을 때, 당시 Array List 의 버 전 번 호 였 습 니 다.MoveNext () 작업 을 수행 할 때 Array List 의 현재 버 전 번호 가 FastArray List Enumerator 대상 이 구 축 된 버 전 번호 와 일치 하 는 지 확인 하고 일치 하지 않 으 면 이상 을 던 집 니 다.
Enumerator 에서 버 전 검사 처 리 를 했 기 때문에 foreach 를 사용 하 는 것 은 스 레 드 가 안전 하고 for 를 사용 하 는 것 은 가끔 입 니 다.왜 일 까요?foreach 를 사용 하여 대상 을 옮 겨 다 니 는 과정 에서 다른 스 레 드 가 List 의 내용 을 수정 하면 추가 하거나 삭제 하면 알 수 없 는 오류 가 발생 하고 foreach 를 사용 하면 오류 정 보 를 정확하게 던 질 수 있 습 니 다.
위 에서 말 한 바 와 같이 결론 은 다음 과 같다.
for 를 사용 하여 더욱 효율 적 입 니 다.
foreach 를 사용 하면 더욱 안전 합 니 다.
그럼 어떻게 선택 할 까요?제 제안 은 전역 적 으로 다 중 스 레 드 가 접근 할 수 있 는 데이터 구조 대상 에서 foreach 를 사용 하 는 것 입 니 다.그리고 로 컬 변 수 는 for 를 사용 하여 효율 과 안전 을 병행 합 니 다!예 를 들 면:
public void F1(IList globalList)
{
IList waitForDeleteList = new ArrayList();
//全局变量,使用foreach,保证线程
foreach (Object item in globalList)
{
if (condition)
{
waitForDeleteList.Add(item);
}
}
//本地变量使用for,保证效率
int waitForDeleteListCount = waitForDeleteList.Count;
for (int i = 0; i < waitForDeleteListCount; ++i)
{
globalList.Remove(waitForDeleteList[i]);
}
}
이상 의 건 의 는 자바 환경 에서 도 사용 하 는 것 에 대해 저 는 JDK 1.4 의 자바 util. Array List 의 실현,. NET Framework 의 실현 과 JDK 의 실현 을 읽 은 적 이 있 습 니 다. 거의 똑 같 습 니 다. 표절 여 부 는 인 견 지 를 보 았 습 니 다.위의 C\# 코드 는 자바 환경 에서 다음 과 같 아야 합 니 다.
public void f1(List globalList) {
List waitForDeleteList = new ArrayList();
//全局变量,使用Iterator遍历,保证线程
Iterator iter = globalList.iterator();
while (iter.hasNext()) {
Object item = iter.next();
if (condition) {
waitForDeleteList.add(item);
}
}
//本地变量使用for,保证效率
int waitForDeleteListCount = waitForDeleteList.size();
for (int i = 0; i < waitForDeleteListCount; ++i) {
globalList.remove(waitForDeleteList.get(i));
}
}
상기 코드 는 이 작업 을 하 는 가장 좋 은 알고리즘 이 아 닙 니 다. 더 높 은 효율 이 필요 하 다 면 다음 과 같이 수정 하 십시오.
C#版本
public void F1(IList globalList)
{
bool condition = true;
IList waitForDeleteList = new ArrayList();
//全局变量,使用foreach,保证线程
int itemIndex = 0;
foreach (Object item in globalList)
{
if (condition)
{
waitForDeleteList.Add(index);
}
++itemIndex;
}
//本地变量使用for,保证效率
int waitForDeleteListCount = waitForDeleteList.Count;
for (int i = waitForDeleteListCount - 1; i >= 0; --i)
{
index = (int) waitForDeleteList[i];
globalList.RemoveAt(itemIndex);
}
}
Java版本:
public void f1(List globalList) {
List waitForDeleteList = new ArrayList();
//全局变量,使用Iterator遍历,保证线程
Iterator iter = globalList.iterator();
int index = 0;
while (iter.hasNext()) {
Object item = iter.next();
if (condition) {
waitForDeleteList.add(new Integer(index));
}
++index;
}
//本地变量使用for,保证效率
int waitForDeleteListCount = waitForDeleteList.size();
for (int i = waitForDeleteListCount - 1; i >= 0; --i) {
index = ((Integer) waitForDeleteList.get(i)).intValue();
globalList.remove(index);
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.