🚀 from error to study/Java

[실습문제/mvc패턴] ArrayList 값 생성 시 1부터 차례대로 부여한 index 값을 ArrayList 값 삭제 시에도 빈 번호 없이 유지하기

천재강쥐 2022. 9. 3. 23:18

[문제]

 

Q. ArrayList<Member>를 통해 값 생성 시 int userNo를 1부터 차례대로 부여함

데이터를 삭제했을 때, 중간값이 삭제되었다면 index에 빈 번호가 생기지 않도록 그 뒤의 값을 당겨오자.

 

현재 존재하는 유저는 4명 (초기화 해 놓은 값)

유저는 차례대로 1~4까지의 userNo를 가지고 있음

유저 3에 대한 데이터를 삭제했을 때

ArrayList<Member>에 남아 있는 userNo는 1, 2, 4

▶ 중간값이 삭제된다면 그 뒤의 값을 당겨 자동으로 1, 2, 3이 되도록 하고 싶음

 

VIEW단의 현재 코드

	// 회원 추가 화면
	public void insertMember() {
		System.out.println("== 새로운 멤버 추가 ==");
		System.out.print("아이디: ");
		String userId = sc.nextLine();
		
		int idCheck = mc.idCheck(userId);
		
		if(idCheck != 0) {
			System.out.println("이미 존재하는 아이디입니다. 다른 아이디를 입력하세요.");
			insertMember();
			return;
		}
		
		System.out.print("비밀번호: ");
		String userPwd = sc.nextLine();
		
		System.out.print("이름: ");
		String userName = sc.nextLine();
		
		System.out.print("나이: ");
		int age = sc.nextInt();
		sc.nextLine();
		
		// 성별 확인받고, M/F가 아닐 경우 다시 입력받기 위해 변수만 따로 빼고 판별식은 while로 묶음
				char gender = 0;
				
				while (true) {
				
				System.out.print("성별(M/F): ");
				gender = sc.nextLine().toUpperCase().charAt(0);
				
				if(gender != 'M' && gender != 'F') {
					System.out.println("성별 재확인 후 알파벳 M(m) 또는 F(f)으로 입력하세요.");
					continue;
				}
					break;
				}
		
		System.out.print("이메일: ");
		String email = sc.nextLine();
		
		System.out.print("휴대폰번호: ");
		String phone = sc.nextLine();
		
		int result = mc.insertMember(userId, userPwd, userName, age, gender, email, phone);
		
		if(result > 0) {
			System.out.println("성공적으로 추가되었습니다.");
		} else {
			System.out.println("곡 추가에 실패했습니다.");
		}

	}

	// 회원 삭제 화면
	public void deleteMember() {
		System.out.println("회원을 삭제합니다.");
		System.out.print("삭제할 회원의 아이디: ");
		String userId = sc.nextLine();
		
		System.out.print("삭제 후 복구할 수 없습니다. 정말 삭제하시겠습니까? (Y/N): ");
		char answer = sc.nextLine().toUpperCase().charAt(0);
		
		int result = mc.deleteMember(userId);
		
		if(answer == 'Y') {
			if(result > 0) {
				System.out.println("성공적으로 삭제되었습니다.");
			} else {
				System.out.println("일치하는 아이디가 없으므로 삭제할 수 없습니다.");
			}
		
		}
		
	}

}

 

controller단의 현재 코드

	{
		// 초기화 블록
		list.add(new Member(1, "user01", "pass01", "김유저", 28, 'F', "user01@naver.com", "010-1234-5678"));
		list.add(new Member(2, "user02", "pass02", "이사람", 20, 'M', "user02@gmail.co.kr", "010-2222-9999"));
		list.add(new Member(3, "user03", "pass03", "최고당", 25, 'F', "user03@daum.net", "010-4812-4212"));
		list.add(new Member(4, "user04", "pass04", "최저당", 21, 'M', "user04@facebook.co.kr", "010-8412-4105"));
		
	}
    
    	// 회원 추가
	public int insertMember(String userId, String userPwd, String userName, int age, char gender, String email, String phone) {
		
		int before = list.size();
		
		// 초기화 블록 적용해서 시작 값을 3으로 해 줘야 됨
		int userNo = list.size();
		userNo = list.size() + 1;
		
		// 문제점
		// 현재 중간 번호의 유저를 삭제했을 때 기존에 설정해 준 userNo가 그대로 유지됨
		// => 1~4까지 존재할 때 3번째를 지우면 남은 유저의 번호는 1, 2, 4
		//    이 상태에서 유저를 한 번 더 추가할 경우 userNo 4가 2명이 됨
 	        // => 삭제 메소드에서 해결해야 함!
		
		list.add(new Member(userNo, userId, userPwd, userName, age, gender, email, phone));
		
		return list.size() - before;
	}


	// 회원 삭제
	public int deleteMember(String userId) {
		
		int result = 0;
		
		for(int i = 0; i < list.size(); i++) {
			
			if(list.get(i).getUserId().equals(userId)) {
			
				list.remove(i--);
				result++;
				
			}
			
		}

[실패 방법]  이라기보다 생각을 1번 덜 해서 틀린 방법

어쨌든 list를 모두 뒤져봐야 삭제할 아이디를 찾을 수 있으니까 for문에 조건을 넣어야 함

int userNo 생성 후 기존 userNo에 대한 값을 받아올 수 있게 list.get(i).getUserNo()로 초기화

result가 0이 아니라면 삭제된 값이 있다는 뜻이므로 삭제된 index 뒤의 값들을 result(삭제된 수)만큼 당겨 줘야

 

userNo 1 2 3 4
index(=i) [0] [1] [2] [3]

이 상태에서 userNo 3을 삭제하면

 

userNo 1
(index + 1)
2
(index + 1)
                 3                   4
(index + 2)
index(=i) [0]
[1] [                2                ] [2]
index는 자동으로 바뀜

그리고 userNo값은 result(삭제된 수)만큼 마이너스 되어야 함

즉,

index = i이고,

삭제된 값보다 이전의 UserNo는 i보다 1 크고,

삭제된 값보다 이후의 UserNo는 i보다 1  초과하여 큼

 

삭제된 값이 1개일 때 userNo 4의 값은 [2] 인덱스이므로 userNo와 index는 2 차이남

삭제된 값이 2개일 때 userNo 2, 3이 지워졌다면? userNo 4의 index는 1이므로 3 차이 날 것!

▶ 삭제된 값보다 이후의 UserNo는 i보다 1  초과하여 큼을 재확인!

 

i+1 기준으로  userNo가 더 크다면 그 값들만 바꿔 줌

 

따라서 조건은 result !=0, userNo > i+1 두 가지를 모두 만족해야 함!

	// 회원 삭제
	public int deleteMember(String userId) {
		
		int result = 0;
		
		for(int i = 0; i < list.size(); i++) {
			
			if(list.get(i).getUserId().equals(userId)) {
			
				list.remove(i--);
				result++;
				
			}
			
			// 삭제했을 때 지워진 데이터보다 큰 인덱스의 UserNo를 result만큼 빼 주면 되지 않을까?
			int userNo = list.get(i).getUserNo();
			
			// 삭제되었을 때 userNo를 result의 수만큼 당겨 줘야 됨
			if(result != 0 && userNo > i+1) {
						
				list.set(i, new Member(list.get(userNo - result).getUserNo(), list.get(i).getUserId(), list.get(i).getUserPwd(), list.get(i).getUserName(),
									  list.get(i).getAge(), list.get(i).getGender(), list.get(i).getEmail(), list.get(i).getPhone()));
			}
			
		}
		
		return result;
	}

}

띠로리...


[해결 방법]

 

위 방법에서 오류가 난 이유는 기껏 계산법 잘 작성해 놓고 대입을 잘못해서

list.get(userNo - result).getUserNo()를 구하면

결국 userNo가 아닌 다 구해 놓은 userNo를 index에 대입하는 꼴!

자바도 띠용때용 나도 띠용때용인 것이다

 

그러니까 나는 잘 구해 놓은 userNo - result를 new Member의 userNo에 넣어 주기만 하면

 

	// 회원 삭제
	public int deleteMember(String userId) {
		
		int result = 0;
		
		for(int i = 0; i < list.size(); i++) {
			
			if(list.get(i).getUserId().equals(userId)) {
			
				list.remove(i--);
				result++;
				
			}
			
			// 삭제했을 때 지워진 데이터보다 큰 인덱스의 UserNo를 result만큼 빼 주면 되지 않을까?
			int userNo = list.get(i).getUserNo();
			
			// 삭제되었을 때 userNo를 result의 수만큼 당겨 줘야 됨
			if(result != 0 && userNo > i+1) {
						
				list.set(i, new Member(userNo - result, list.get(i).getUserId(), list.get(i).getUserPwd(), list.get(i).getUserName(),
									  list.get(i).getAge(), list.get(i).getGender(), list.get(i).getEmail(), list.get(i).getPhone()));
			} // => 진행했을 때 잘됨!!
			
		}
		
		return result;
	}

}

코드를 다시 한번 정리하자면 위와 같음

 

user02, user03을 삭제하고 새로운 유저 한 명을 추가했을 때에도

userNo가 잘 지정되는 모습이다