연속되는 숫자와 문자를 (연속하는 횟수 + 문자or숫자 형태로) 압축해서 리턴하라.
public class CompressString {
public String compressString(String str) {
String result ="";
char now = ' ';
for(int i=0; i<str.length(); i++){
if(str.charAt(i)!=now) {
now = str.charAt(i);
char nextCh = ' ';
int j = i;
int count = 1;
if (j + 1 < str.length()) {
nextCh = str.charAt(j + 1);
while (now == nextCh) {
count++;
j++;
if (j + 1 < str.length()) nextCh = str.charAt(j + 1);
else break;
}
}else result += str.charAt(i);
if(count==1) result += now;
else result = result + count + now;
}
}
return result;
}
}
//입력
compressString.compressString("qwweeerrrrtt")
//출력
q2w3e4r2t
//정답
qww3e4rtt
문제를 제대로 파악하자... 3회 이상 반복될 때만 압축해야 한다.
public String compressString(String str) {
String result ="";
char now = ' ';
int count = 1;
for(int i=0; i<str.length(); i++){
if(str.charAt(i)!=now) {
now = str.charAt(i);
char nextCh = ' ';
int j = i;
count = 1;
if (j + 1 < str.length()) {
nextCh = str.charAt(j + 1);
while (now == nextCh) {
count++;
j++;
if (j + 1 < str.length()) nextCh = str.charAt(j + 1);
else break;
}
}else result += str.charAt(i);
---------------------------------수정된 부분---------------------------------
if(count<3) result += now;
else result = result + count + now;
}else if(count<3) result += now;
---------------------------------수정된 부분---------------------------------
}
return result;
}
//입력1
"qwweeerrrrtt"
//출력1
qww3e4rtt
//입력2
"EQTWVOQQQVDVRC"
//출력2
EQTWVO3QVDVRCC
일부 케이스는 되는데 일부 케이스는 압축이 제대로 안되고 있다.
마지막 요소가 연속되지 않고 종료할 경우 result에 값이 두번 들어가고 있다.
코드 작성중에 여러가지 시도를 해보다 남겨둔 코드였는데 지우는 것을 잊어버리고 실수했다.
package CodeStatesAlgorithms;
public class CompressString {
public String compressString(String str) {
String result ="";
char now = ' ';
int count = 1;
for(int i=0; i<str.length(); i++){
if(str.charAt(i)!=now) {
now = str.charAt(i);
char nextCh = ' ';
int j = i;
count = 1;
if (j + 1 < str.length()) {
nextCh = str.charAt(j + 1);
while (now == nextCh) {
count++;
j++;
if (j + 1 < str.length()) nextCh = str.charAt(j + 1);
else break;
}
---------------------------------수정된 부분---------------------------------
} //else result += str.charAt(i);
---------------------------------수정된 부분---------------------------------
if(count<3) result += now;
else result = result + count + now;
}else if(count<3) result += now;
}
return result;
}
}
모든테스트 케이스 통과
Spring MVC =
spring-webmvc
- 서블릿(Servlet) API를 기반으로 클라이언트의 요청을 처리하는 모듈
- 웹 프레임워크의 한 종류 (Spring MVC 프레임워크라고도 부름)
- 클라이언트의 요청을 편리하게 처리해주는 프레임워크다.
서블릿(Servlet)
- 웹 서버의 성능을 향상하기 위해 사용되는 자바 클래스의 일종
- 클라이언트의 요청을 처리하도록 특정 규약에 맞추어서 Java 코드로 작성하는 클래스 파일
cf. 아파치 톰캣(Apache Tomcat)
은 서블릿들이 웹 애플리케이션으로 실행이 되도록 해주는 서블릿 컨테이너(Servlet Container) 중 하나
Spring MVC 중 M
Model
- 클라이언트에게 응답으로 돌려주는 작업의 처리 결과 데이터
Spring MVC 중 V
View
- Model 데이터를 이용해서 웹브라우저 같은 클라이언트 애플리케이션의 화면에 보여지는 리소스(Resource)를 제공하는 역할
HTML 페이지의 출력
PDF, Excel 등의 문서 형태로 출력
XML, JSON 등 특정 형식의 포맷으로의 변환
public class Coffee {
private String korName;
private String engName;
private int price;
public Coffee(String korName, String engName, int price) {
this.korName = korName;
this.engName = engName;
this.price = price;
}
}
Gson이라는 라이브러리를 사용해서 Coffee 클래스의 객체를 JSON 포맷 형태로 출력
public class JsonExample {
public static void main(String[] args) {
Coffee coffee = new Coffee("아메리카노", "Americano", 3500);
Gson gson = new Gson();
String jsonString = gson.toJson(coffee);
System.out.println(jsonString);
}
}
//출력
{"korName":"아메리카노","engName":"Americano","price":3500}
JSON 포맷은 기본적으로{”속성”:”값”}
형태다.
위와 반대의 과정을 아래 툴로 연습해보며 JSON 형태에 익숙해질 수 있었다.
JSON 포맷의 문자열을 Java 클래스로 변경해주는 온라인 툴
Spring MVC 중 C
Controller
- 클라이언트 측의 요청을 직접적으로 전달 받는 엔드포인트(Endpoint)로써 Model과 View의 중간에서 상호 작용을 해주는 역할
- 클라이언트 측의 요청을 전달 받아서 비즈니스 로직을 거친 후에 Model 데이터가 만들어지면, 이 Model 데이터를 View로 전달하는 역할
Client가 요청 데이터 전송
→ Controller가 요청 데이터 수신
→ 비즈니스 로직 처리
→ Model 데이터 생성
→ Controller에게 Model 데이터 전달
→ Controller가 View에게 Model 데이터 전달
→ View가 응답 데이터 생성
cf.
DispatcherServlet처럼 애플리케이션의 가장 앞단에 배치되어 다른 구성요소들과 상호작용하면서 클라이언트의 요청을 처리하는 패턴을 Front Controller Pattern이라고 한다.
주로 사용하는 패키지 구조 두가지
테스트와 리팩토링이 용이하고, 향후에 마이크로 서비스 시스템으로의 분리가 상대적으로 용이한 기능 기반 패키지 구조 사용을 권장하기 때문에 학습과정에서는 기능 기반 패키지 구조를 따를 예정이다.
@SpringBootApplication
을 추가한다.SpringApplication.run()
을 호출하면 Spring Boot 기반의 애플리케이션으로 동작한다.@RestController
를 클래스에 추가함으로써 해당 클래스를 REST API의 리소스(자원, Resource)를 처리하기 위한 API 엔드포인트로 동작하게 해준다.@RequestMapping
을 Controller 클래스 레벨에 추가하여 클래스 전체에 사용되는 공통 URL(Base URL)을 설정할 수 있다.@SpringBootApplication
@Component
가 붙은 클래스를 검색한 후(scan), Spring Bean으로 등록하는 기능을 활성화@Configuration
이 붙은 클래스를 자동으로 찾아주고, 추가적으로 Spring Bean을 등록하는 기능을 활성화SpringApplication.run(~~Application.class, args);
@RestController
클래스가 REST API의 리소스(자원, Resource)를 처리하기 위한 API 엔드포인트로 동작함을 정의한다.
애플리케이션 로딩 시, Spring Bean으로 등록해준다.
@RequestMapping
produces
애트리뷰트(Attribute)
@RequestMapping(value = "/v1/members", produces = {MediaType.APPLICATION_JSON_VALUE})
위 예시의 MediaType.APPLICATION_JSON_VALUE
부분은 JSON 형식의 데이터를 응답 데이터로 전송하겠다는 의미다.
위와 같이 produces값을 지정해주지 않으면 문자열 자체를 전송한다.
@PostMapping
@RequestParam
map 메서드 put()
, replace()
차이
Map<String, Integer> map = new HashMap<>();
map.put("key1", 1);
map.put("key2", 2);
map.put("key1", 3); // key1의 value를 3으로 업데이트
map.put("key3", 4); // key3의 value를 4로 추가
map.replace("key2", 5); // key2의 value를 5로 업데이트
map.replace("key4", 6); // key4가 존재하지 않기 때문에, 어떠한 동작도 수행하지 않음
put은 key가 해당하는 엔트리가 없어도 새로 만들어서라도 추가해줌
replace는 존재하지 않으면 아무것도 안함
ResponseEntity
사용법
http 상태코드를 이용하면 됨.
// members + 200 OK
return new ResponseEntity(members, HttpStatus.OK);
// 204 No Content
return new ResponseEntity(HttpStatus.NO_CONTENT);
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/v1/members")
public class MemberController {
private final Map<Long, Map<String, Object>> members = new HashMap<>();
@PostConstruct
public void init() {
Map<String, Object> member1 = new HashMap<>();
long memberId = 1L;
member1.put("memberId", memberId);
member1.put("email", "hgd@gmail.com");
member1.put("name", "홍길동");
member1.put("phone", "010-1234-5678");
members.put(memberId, member1);
}
// 1. 회원 정보 수정을 위한 핸들러 메서드 구현
@PatchMapping("/{member-id}")
public ResponseEntity patchMember(@PathVariable("member-id")long memberId, // url에 있는 특정한 값을 뽑아오는 애너테이션 (http://localhost:8080/v1/members/1)
@RequestParam("phone") String phone){ // requstParam = 사용자 입력 중 바디에 있는 값을 가져온다.
members.get(memberId).replace("phone", phone);
return new ResponseEntity(members, HttpStatus.OK);
}
// 2. 회원 정보 삭제를 위한 핸들러 메서드 구현
@DeleteMapping("/{member-id}")
public ResponseEntity deleteMember(@PathVariable("member-id")long memberId){
members.remove(memberId);
System.out.println("삭제성공");
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
}
@PathVariable
= url에 있는 특정한 값을 뽑아오는 애너테이션 http://localhost:8080/v1/members/1
@RequestParam
= 사용자 입력 중 바디에 있는 값을 뽑아주는 애너테이션
package com.codestates.coffee;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/v1/coffees")
public class CoffeeController {
private final Map<Long, Map<String, Object>> coffees = new HashMap<>();
@PostConstruct
public void init() {
Map<String, Object> coffee1 = new HashMap<>();
long coffeeId = 1L;
coffee1.put("coffeeId", coffeeId);
coffee1.put("korName", "바닐라 라떼");
coffee1.put("engName", "Vanilla Latte");
coffee1.put("price", 4500);
coffees.put(coffeeId, coffee1);
}
//---------------- 여기서 부터 아래에 코드를 구현하세요! -------------------//
// 1. 커피 정보 수정을 위한 핸들러 메서드 구현
@PatchMapping("/{coffee-id}")
public ResponseEntity patchMember(@PathVariable("coffee-id")long coffeeId,
@RequestParam("korName") String korName,
@RequestParam("price") int price){
coffees.get(coffeeId).replace("korName", "바닐라 빈 라떼");
coffees.get(coffeeId).replace("price", 5000);
return new ResponseEntity(coffees,HttpStatus.OK);
}
// 2. 커피 정보 삭제를 위한 핸들러 서드 구현
@DeleteMapping("/{coffee-id}")
public ResponseEntity deleteMember(@PathVariable("coffee-id")long coffeeId){
coffees.remove(coffeeId);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
}
이렇게 코드 내에서 직접적으로 수정해줄 수도 있다.
실습 중 @RequestParam, @PathVariable차이를 정확히 몰라서 고생했었다.
@PathVariable은 값을 하나만 받아올 수 있으므로, 여러 개 데이터를 받아올 때는 @RequestParam을 쓴다!