for문, do-While문, 입출력, 배열
1. 입력값 중에 최댓값을 구하는 메서드
public class Yoon {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("숫자를 입력해주세요.");
String[] str = br.readLine().split(" ");
int[] arr = new int[str.length];
for(int i = 0; i < arr.length; i++){
arr[i] =Integer.parseInt(str[i]);
}
int max = arr[0];
for(int j = 1; j<arr.length; j++){
if(max < arr[j]){
max = arr[j];
}
}
System.out.println("최댓값은"+max+"입니다");
}
}
" "를 기준으로 입력값을 str배열에 잘라서 삽입합니다.
Scanner를 이용하면 간편하지만 성능면에서는 Buffer를 이용한 BufferedReeader보다 느립니다.
입출력 경우에는 성능이라고 보면 속도의 차이라고 봅니다.
이렇게 위와 같이 간단한 예제에서는 차이가 별로 없겠지만 좀 더 많은 데이터들을 입출력을 하는 경우에는 성능차이가 납니다.
백준에서 한 번 메모리나 처리속도를 측정해봤습니다
public static void main(String[] args)throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
System.out.println(a + b);
} //BufferedReader를 이용.
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int a =sc.nextInt();
int b =sc.nextInt();
System.out.println(a+b);
}//Scanner를 이용.
코드의 수는 Scanner가 적습니다 하지만,
위에가 Scanner를 이용한 것이고, 밑에가 BufferedReader를 이용한 것입니다.
이렇게 짧은 코드에도 성능차이가 존재합니다.
Scanner는 1KB 크기의 버퍼를 갖기 때문에 입력이 바로 전달이 됩니다. 그 반면에
BufferedReader는 8KB 크기의 버퍼를 가져 buffer에 입력들을 저장하였다 한 번에 전송하기 때문에 속도가 더 빠릅니다.
그리고 다시 본론으로 돌아와, arr에 입력된 값들을 담아두고 max에 arr배열의 0번째값을 초기화를 해주고,
차례대로 처음부터 배열의 끝까지 검색을 해주면 원래 있던 값보다 클 경우에는 max값을 변경을 해주어 최종적으로 최댓값을 구합니다.
2. 중간값을 구하는 메서드.
public static int middle(int a, int b, int c) {
int[] arr = {a, b, c};
int middle = 0;
if (a >= b) {
if (b >= c){
return b;
}else if(a <= c){
return a;
}else return c;//여기까지는 수가 크면 중간값이 바로 나오고 아니면 다 같은값으로 나오기때문에 아무거나 리턴해도 중간값이다.
}else if(a > c){
return a;
}else if(b > c){
return c;
}else return b;
배열의 최솟값과 최댓값을 구하는 것은 전체 탐색하여 값만 바꿔주면되지만,
중간값을 구하는경우는 경우의 수가 13가지가 존재하기때문에 경우의 수만 잘 따져준다면, 어려움이 없이 풀 수 있다.
3. 1부터 n까지의 하는 메서드(for,do-while)
public class Main {
public static void main(String[] args){
nSum(3); //for문을 이용한 정수의합
doWhile(2); //do-while문을 이용한 정수의합
}
public static void nSum(int a){
int i =0;
int sum = 0;//값의 합
for( i = 1; i <= a; i++){
sum += i;
System.out.println(i);
}
System.out.println(i);
}
public static void doWhile(int a) {
int sum = 0;//합
int i =1;
do{
sum += i;
i++;
}while (i<=a);
System.out.println("합은"+sum);
}
}
for문과 달리 do-while문은 do{}의 부분을 일단 먼저 실행을 한 후에 while문의 조건을 판단을 한 후에 true일 경우에는 계속 do{}영역의 부분을 실행을 하며, while문이 false가 될 때까지 반복된다.
이것이 사전 판단 반복과 사후 판단 반복의 차이입니다.
4.구구단만들기&별찍기
public class Main {
public static void main(String[] args){
a(3);//구구단출력.
b(8);//피라미드형태의 별찍기
}
public static void a(int n){
for(int i = 1; i <= n; i++){
for(int j = 1; j<= n; j++){
System.out.println(i+"*"+j+"="+(i*j));
}
}
}
public static void b(int n){
for(int i = 0; i < n; i++){
for(int k = 0; k < n-i; k++){
System.out.print("");
}
for(int j = 0; j < i*2+1; j++){
System.out.print("*");
}
System.out.println();
}
}
}
위에 코드는 중첩for문을 이용하여 만든 방식입니다.
5.배열복사&배열의 역순정리.
public class Main {
public static void main(String[] args){
cloneArr(6);//clone메서드를 이용한 배열복사
String[] a = {"훈이", "유리", "철수", "짱구"}; //임의의 배열선언.
rArr(a);//a의 배열을 역순으로 정리.
}
public static void cloneArr(int n){
int [] a = new int[n];//a의 배열을 만들고
int j = 0;
for(int i = 0; i < n; i++){//배열에 값을 1부터 넣어준다.
a[i] = j;
j++;
}
int[]b= a.clone();//a의 배열을 b로 복제
for(int c :b){
System.out.println(c);
}
}
public static void rArr(String[] a ){
String k =" ";//변수의 값을 바꾸기 위하여 잠시 보관용 변수.
for(int i = 0; i<a.length/2; i++){
k = a[i];
a[i] = a[a.length-1-i];
a[a.length-1-i] = k;
}
for(int i = 0; i < a.length; i++){
System.out.print(a[i]+' ');
}
}
}
위에 배열의 역순의 방법은 for문을 이용하여 배열의 첫번째 인덱스와 마지막 인덱스를 계속하여 교체하는방법으로 역순으로 정리할 수 있습니다.
두번째로는 배열의 복사인데 자바에서는 배열을 복사하는메서드는 여러가지 존재합니다.
위의 방식은 Object.clone()의 방식을 사용하였습니다.
또 다른 배열복제 메서드는 아래와 같습니다.
Arrays.copyOf()
Arrays.copyOfRange()
System.arraycopy()
왜 이렇게 배열복사 메서드가 여러가지일까요?
배열의 얕은 복사와 깊은 복사가 있기 때문입니다.
간단한 예를 보면,
public static void main(String[] args) {
int[] n = {1, 2, 3, 4, 5, 6};
int[] m = n;
System.out.println(Arrays.toString(m)); //->[1, 2, 3, 4, 5, 6]
System.out.println(n); //배열의 주소[I@7c30a502
System.out.println(m); //배열의 주소[I@7c30a502
n[0] =2;//값 변경.
System.out.println(Arrays.toString(m));//->[2, 2, 3, 4, 5, 6]
}//배열의 얕은 복사
위에 코드를 보면 얕은복사 일 경우입니다
사실상 복사라는 것 보다는 배열n를 참조하여 사용한다고 생각을 하시면 될 것 같습니다.
배열 n의 값이 바뀌면 배열m도 따라서 똑같이 바뀌며 주소값도 서로 같습니다.
public static void main(Sting[]args){
int[] n = {1, 2, 3, 4, 5, 6};
int[] m = new int[n.length];
for(int i = 0; i < n.length; i++){
m[i] = n[i];
}
//배열의 깊은복사
System.out.println(Arrays.toString(m));//[1, 2, 3, 4, 5, 6] 복사완료
System.out.println(n);//[I@7c30a502 주소값
System.out.println(m);//[I@49e4cb85
n[0] =2;
System.out.println(Arrays.toString(n)); //->[2, 2, 3, 4, 5, 6]
System.out.println(Arrays.toString(m)); //->[1, 2, 3, 4, 5, 6]
}
위와 같은 경우는 깊은복사 일 경우입니다
얕은복사와 달리 참조하는게 아니라 그대로 원본의 배열을 그대로 받아서 저장을 하며, 배열의 주소값도 다르며,
원본의 배열의 값이 달라진다고 한들, 복사한 배열은 달라지지 않습니다.
public static void main(String[] args){
int[] a = {1,2,3,4,5,6,7};
int[] b= Arrays.copyOf(a, a[4]);// a의 배열을 a의 원하는 인덱스까지 복사.
System.out.println(Arrays.toString(b));//->{1,2,3,4,5}
int[] c = Arrays.copyOfRange(a,a[1],a[4]);//배열의 시작점 끝점 지정 할 수있음.
System.out.println(Arrays.toString(b));//->{3,4,5}
int[] d={12,13,14,15,16,17};
System.arraycopy(a,0,d,0,3);//(배열원본, 배열원본의 복사시작점, 복사를하여서 받을 배열, 복사시작배열, 복사원소를 받을개수)
System.out.println(Arrays.toString(d));//->{1,2,3,15,16,17}
}
또 다른 메서드들은 이렇게 위와같이 시작점과 끝점을 지정하여 배열을 복사할 수 있습니다