<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>0_0ni.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 10 Mar 2023 01:02:55 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. 0_0ni.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/0_0ni" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Port]]></title>
            <link>https://velog.io/@0_0ni/Port</link>
            <guid>https://velog.io/@0_0ni/Port</guid>
            <pubDate>Fri, 10 Mar 2023 01:02:55 GMT</pubDate>
            <description><![CDATA[<h3 id="포트port">포트(Port)</h3>
<p>포트란 <strong>&#39;논리적인 접속장소&#39;</strong>를 뜻하며, 인터넷 프로토콜인 TCP/IP를 사용할 때 클라이언트 프로그램이 네트워크 상의 특정 서버 프로그램을 지정하는 방법으로 사용한다.</p>
<p>한 서버 인스턴스에서 여러 개의 서버를 동시 실행할 수 있으므로, 이 경우 IP 주소 만으로는 어느 서버로 요청을 보내는지 특정하기 힘들다. 이 때 포트번호를 통해 receiver를 특정하여 어느 서버로 보내는 요청인지 특정할 수 있다.</p>
<p>포트번호는 0 ~ 65,535 까지 사용할 수 있으며, 이 중에서 0 ~ 1023번 까지의 포트 번호는 주요 통신을 위한 규약에 따라 이미 정해져 있는 포트이다.</p>
<blockquote>
<ul>
<li><strong>Well-known port</strong> : 0 ~ 1023 &gt; 시스템 사용 번호 (슈퍼유저 권한 필요)</li>
</ul>
</blockquote>
<ul>
<li><strong>Registered port</strong> : 1024 ~ 49151 &gt; 특정 프로토콜이나 어플리케이션에서 사용하는 번호 (슈퍼유저 권한 필요X)</li>
<li><strong>Dynamic port</strong> : 49152 ~ 65535 &gt; 어플리케이션 또는 임시 사용 번호 </li>
</ul>
<h3 id="자주-사용되는-포트-번호">자주 사용되는 포트 번호</h3>
<p> 번호 / 프로토콜 / 통신 프로토콜 / 설명</p>
<ul>
<li><strong>80</strong> : <strong>HTTP</strong> / TCP / 웹 서버 접속</li>
<li><strong>443</strong> : <strong>HTTPS</strong> / TCP / 웹 서버 접속(SSL)</li>
<li><strong>110</strong> : POP3 / TCP / 메일 읽기</li>
<li><strong>25</strong> : SMTP / TCP / 메일 서버간 메일 전송</li>
<li><strong>23</strong> : TENLET</li>
<li><strong>53</strong> : <strong>DNS</strong> / UDP / DNS 질의</li>
<li><strong>123</strong> : NTP / TCP / 시간 동기화</li>
<li><strong>20</strong> : <strong>FTP</strong> / TCP / 데이터 전송</li>
<li><strong>21</strong> : <strong>FTP</strong> / TCP / FTP 제어. 서버와 클라이언트 사이의 파일 전송을 위한 프로토콜</li>
<li><strong>22</strong> : SSH(Secure Shell) / TCP / 컴퓨터 원격 로그인. 다른 사용자가 세션을 엿듣지 못하도록 세션을 감싸 보안 및 안정성을 높임. 네트워크 상의 다른 컴퓨터에 로그인하거나 원격 시스템에서 명령을 실행하고 다른 시스템으로 파일을 복사할 수 있도록 해주는 프로토콜. Linux 계열에서 사용한다.</li>
</ul>
<p>참고 
<a href="https://ittrue.tistory.com/185?category=928607">https://ittrue.tistory.com/185?category=928607</a>
<a href="https://sevendollars.tistory.com/43">https://sevendollars.tistory.com/43</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring Batch] 스프링배치 완벽가이드 내용정리]]></title>
            <link>https://velog.io/@0_0ni/Spring-Batch-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B0%B0%EC%B9%98-%EC%99%84%EB%B2%BD%EA%B0%80%EC%9D%B4%EB%93%9C</link>
            <guid>https://velog.io/@0_0ni/Spring-Batch-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B0%B0%EC%B9%98-%EC%99%84%EB%B2%BD%EA%B0%80%EC%9D%B4%EB%93%9C</guid>
            <pubDate>Thu, 09 Mar 2023 08:48:45 GMT</pubDate>
            <description><![CDATA[<p>스프링배치는 코커와 인프라스트럭처를 애플리케이션이 감싸는 구조로 되어 있다.</p>
<h3 id="애플리케이션-레이어">애플리케이션 레이어</h3>
<p><strong>개발자가 개발한 코드</strong>
배치 처리 구축에 사용되는 모든 사용자 코드 및 구성을 포함한다.
업무 로직과 서비스 및 잡 구조화와 관련된 구성까지도 애플리케이션 레이어에 포함된다.
애플리케이션 레이어가 최상위에 있는 것이 아니라, 다른 두 레이어인 코어와 인프라스트럭처를 애플리케이션이 감싸고 있는 것으로 이해해야 한다.</p>
<p>애플리케이션 레이어는 그 다음 레이어인 <strong>코어 레이어와 상호작용</strong>하는 데 대부분의 시간을 소비한다.</p>
<h3 id="코어-레이어">코어 레이어</h3>
<p><strong>배치 영역을 구성하는 실제적인 컴포넌트로 구성</strong>
배치 도메인을 정의하는 모든 부분이 포함된다.
코어 컴포넌트의 요소에는 Job 및 Step 인터페이스와, 잡 실행에 사용되는 인터페이스, 즉 JobLauncher 및 JobParameters 등이 있다.</p>
<h3 id="인프라스트럭처-레이어">인프라스트럭처 레이어</h3>
<p><strong>ItemReadr, IremWriter 및 재시작과 관련된 문제 해결 가능한 클래스와 인터페이스 제공</strong>
배치 처리를 위해 파일, DB 등으로부터 읽고 쓸 수 있고,
잡 수행에 실패한 이후 재시도될 때 어떤 일을 수행할지 다룰 수 있다.</p>
<hr>
<p>스프링 배치는 일반적으로 스케줄러이거나, 스케줄링 기능을 갖고 있다고 오해할 수 있으나 그렇지 않다. 
프레임워크 내에는 주어진 시간 또는 주어진 이벤트에 따라 잡이 실행되도록 스케줄링 하는 기능이 없다. 크론이나 쿼츠, 컨트롤-M 같은 엔터프라이즈 스케줄러를 이용하는 등 잡을 구동 시키는 여러 방법이 있으나, <strong>프레임워크 내에 존재하지는 않는다.</strong></p>
<h3 id="스프링으로-잡-정의하기">스프링으로 잡 정의하기</h3>
<h4 id="job">Job</h4>
<p>중단이나 상호작용 없이, 처음부터 끝까지 실행되는 처리
여러 개의 스텝이 모여 잡을 이룬다.
각 스텝에는 관련된 입력과 출력이 있을 수 있다. </p>
<pre><code class="language-Java">// 스프링 배치 잡 정의 예제
@Bean
public AccountTasklet accountTasklet() {
    return new AccountTasklet();
}

@Bean
public job accountJob() {
    Step accountStep = 
        this.stepBuilderFactory
            .get(&quot;accountStep&quot;)
            .tasklet(accountTasklet())
              .build();

return this.jobBuilderFactory
           .get(&quot;accountJob&quot;)
           .start(&quot;accountStep&quot;)
           .build();
}</code></pre>
<p>위 소스 내에 두 개의 Bean이 작성되었다.</p>
<p>1) AccountTasklet : 커스텀 컴포넌트. 스텝이 동작하는 동안 비즈니스 로직 수행
스프링 배치는 AccountTasklet이 완료될 때까지 단일 메서드(excute 메서드)를 반복해서 호출하는데, 이때 각각은 새 트랜잭션으로 호출된다.</p>
<p>2) 실제 스프링 배치 잡 : 팩토리가 제공하는 빌더를 사용해, AccountTasklet을 감싸는 스텝 하나를 생성한다. 그 다음 Job Builder를 사용해 스텝을 감싸는 잡을 생성한다.
<strong>스프링 부트</strong>는 애플리케이션 기동 시 해당 잡을 찾아내 자동으로 실행시킨다. </p>
<p>스프링 배치는 스프링 기반으로 구축되었기 때문에, <strong>의존성 주입 / AOP(Aspect-Oriented Programming) / 트랜잭션 관리 / 일반적인 작업(JDBC, JMS, 전자 메일 등)</strong> 을 위한 기능을 제공한다.</p>
<p>책 예제코드 &gt; <a href="https://github.com/Apress/def-quide-spring-batch">https://github.com/Apress/def-quide-spring-batch</a></p>
<hr>
<h3 id="잡job">잡(Job)</h3>
<p><img src="https://velog.velcdn.com/images/0_0ni/post/537b7653-f8d0-4a46-9760-d53c5be4df4b/image.png" alt=""></p>
<p>자바나 XML을 사용해 구성된 배치 잡은, 상태를 수집하고 이전 상태 -&gt; 다음 상태로 전환된다.
개념적으로 스프링 배치 잡은 <strong>상태 기계(State Machine)</strong>에 지나지 않는다.</p>
<p>스프링배치에서 가장 일반적으로 상태를 보여주는 단위는 <strong>스텝</strong>이다.</p>
<blockquote>
<p>ex) 업무 시간 이후에 고객의 은행계좌 처리</p>
</blockquote>
<ul>
<li>스텝1 : 다른 시스템에서 수신한 거래 정보 파일 읽어와 DB에 저장</li>
<li>스텝2 : 모든 입금 정보를 계좌에 반영</li>
<li>스텝3 : 모든 출금 정보를 계좌에 반영</li>
</ul>
<h3 id="스텝">스텝</h3>
<p><strong>잡을 구성하는 독립된 작업의 단위</strong>
Tasklet 기반 스텝과 Chunk 기반 스텝이 있으며, 태스크릿 기반 스텝의 구조가 더 간단하다.</p>
<h3 id="tasklet-기반-스텝">Tasklet 기반 스텝</h3>
<p>Tasklet을 구현하여 사용할 수 있으며, 스텝이 중지될 때까지 excute 메소드가 계속 반복해서 수행된다. 이 때 excute 메소드를 호출할 때마다 독립적인 트랜잭션이 얻어진다. 
<strong>초기화, 저장 프로시저 실행, 알림 전송</strong> 등과 같은 잡에서 일반적으로 사용된다.</p>
<h3 id="chunk-기반-스텝">Chunk 기반 스텝</h3>
<p>태스크릿 기반 스텝에 비해 구조가 약간 더 복잡하며, 아이템 기반의 처리에 사용한다.
ItemReader / ItemProcesspr / ItemWriter 라는 3개의 주요 부분으로 구성되며, 이 때 ItemProcessor는 필수는 아니다.
ItemReader와 ItemWriter 만으로도 스텝 실행이 가능한데, 이와 같은 스텝은 일반적으로 데이터 마이그레이션 잡에 많이 사용된다.</p>
<hr>
<ul>
<li>Tasklet : 트랜잭션 내에서 로직이 실행될 수 있는 기능을 제공하는 전략(Strategy) 인터페이스</li>
<li>ItemReader : 스텝 내에서 입력을 제공하는 전략 인터페이스</li>
<li>ItemProcessor : 스텝 내에서 제공받은 개별 아이템에 업무 로직, 검증 등을 적용하는 역할을 수행하는 인터페이스</li>
<li>ItemWriter : 스텝 내에서 아이템을 저장하는 전략 인터페이스</li>
</ul>
<hr>
<p>스프링의 잡 구조화 방법이 갖는 장점 : 각 스텝이 서로 독립적으로 처리될 수 있도록 분리되어 있다. 
유연성 / 유지보수성 / 확장성 / 신뢰성 확보 가능</p>
<hr>
<h3 id="jobrepository">JobRepository</h3>
<p>스프링 배치 아키텍처 내에서 공유되는 주요 컴포넌트 가운데 하나.
배치 수행과 관련된 다양한 수치 데이터(시작 시간, 종료 시간, 상태, 읽기/쓰기 횟수 등) 및 잡의 상태를 유지 관리한다.
JobRepository는 일반적으로 <strong>관계형 데이터베이스</strong>를 사용하며, 스프링 배치 내의 대부분의 주요 컴포넌트가 이를 공유한다. </p>
<p><img src="https://velog.velcdn.com/images/0_0ni/post/1b473ba3-a9bb-4fe1-8f1a-cb82e70c21e8/image.png" alt="잡 컴포넌트 및 관계"></p>
<h3 id="joblauncher">JobLauncher</h3>
<p><strong>잡을 실행</strong>하는 역할 담당. (Job.excute 메서드 호출)
또한 잡의 재실행 가능여부 확인 / 잡의 실행 방법(현재 스레드에서 수행할지, 스레드 풀을 통해 실행할지 등) / 파라미터 유효성 검증 등의 처리를 수행한다.</p>
<p>잡 실행 -&gt; 해당 잡은 각 스텝 실행 -&gt; 각 스텝이 실행되면 JobRepository는 현재 상태로 갱신된다.
즉 실행된 스텝, 현재 상태, 읽은 아이템 및 처리된 아이템 수 등이 모두 JobRepository에 저장된다.</p>
<p>잡과 스텝의 처리 방식은 매우 유사한데, 잡은 구성된 스텝 목록에 따라 각 스텝을 실행한다.
여러 아이템으로 이뤄진 청크의 처리가 스텝 내에서 완료될 때 -&gt; 스프링 배치는 JobRepository 내에 있는 JobExecution 또는 StepException을 현재 상태로 갱신한다.
스텝은 ItemReader가 읽은 아이템의 목록을 따라간다. 스텝이 각 청크를 처리할 때 마다 JobRepository 내 StepExecution의 스탭 상태가 업데이트 된다.
현재까지의 커밋 수, 시작 및 종료시간, 기다 다른 정보 등이 JobRepository에 저장되며, 잡 또는 스텝이 완료되면 JobExecution 또는 StepExecution이 최종 상태로 업데이트 된다. </p>
<h3 id="jobinstance">JobInstance</h3>
<p>스프링 배치 잡의 논리적인 실행(Logical Execution)을 의미.</p>
<p>ex) 거래명세서를 생성하는 statementGenerator 라는 잡이 다른 파라미터로 실행될 때마다 새로운 JobInstance가 생성된다. </p>
<h3 id="jobexecution">Jobexecution</h3>
<p>스프링 배치 잡의 실제 실행(execution)을 의미.
잡을 구동할 때마다 새로운 JobExecution을 얻게 된다. 그러나 잡 실행에 실패한 이후 다시 실행하면, 해당 실행은 앞선 것과 동일한 논리적 실행(파라미터가 동일함)이므로 새로운 JobInstance를 얻을 수 없으나, 두 번째 실제 실행을 추적하기 위한 새로운 JobExecution을 얻을 것이다.
<strong>즉 JobInstance는 여러 개의 JobExecution을 가질 수 있다.</strong></p>
<h3 id="stepexecution">StepExecution</h3>
<p>스텝의 실제 실행(execution)을 의미.
그러나 StepInstance 라는 개념은 존재하지 않는다.
JobExecution은 여러 개의 StepExecution과 연관된다.</p>
<hr>
<h3 id="잡을-병렬화-하는-방법">잡을 병렬화 하는 방법</h3>
<ul>
<li>다중 스레드 스텝을 통한 작업 분할 </li>
<li>전체 스텝의 병렬 실행</li>
<li>비동기 ItemProcessor/ItemWriter 구성</li>
<li>원격 청킹</li>
<li>파티셔닝</li>
</ul>
<h4 id="1-다중-스레드-스텝">(1) 다중 스레드 스텝</h4>
<p>스프링 배치에서 잡은 청크라는 블록 단위로 처리되도록 구성되며, 각 청크는 독립적인 트랜잭션으로 처리된다. 일반적으로 각 청크는 연속해서 처리된다. </p>
<h4 id="2-병렬-스텝">(2) 병렬 스텝</h4>
<p>입력 파일의 데이터를 읽어오는 한 개의 스텝과, DB에 저장하는 일을 하는 한 개의 스텝이 있으나 서로 관련이 없을 경우, 각각 독립 실행되게끔 처리</p>
<h4 id="3-비동기-itemprocessoritemwriter">(3) 비동기 ItemProcessor/ItemWriter</h4>
<h4 id="4-원격-청킹">(4) 원격 청킹</h4>
<p>마스터 노드에서 표준 ItemReader를 사용해 이뤄진다.
입력은 RabbitMQ와 같은 메시지 브로커를 통해 ItemProcessor로 전송된다.
처리가 완료되면 워커는 업데이트된 아이템을 다시 마스터로 보내거나 직접 기록한다.
이 방식은 네트워크 사용량이 많아질 수 있음에 유의해야 하며, 실제 처리에 비해 I/O 비용이 적은 시나리오에 적합하다.</p>
<hr>
<pre><code class="language-java">@EnableBatchProcessing
@SpringBootApplication
public class HelloWorldApplication {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Step step() {
        return this.stepBuilderFactory.get(&quot;step1&quot;)
                                .tasklet(new Tasklet() {
                                    @Override
                                    public RepeatStatus execute(StepContribution contribution,
                                    ChunkContext chunkContext) {
                                        System.out.println(&quot;Hello, World!&quot;);
                                        return RepeatStatus.FINISHED;
                                    }
     }).build();
 }

     @Bean
     public Job job() {
         return this.jobBuilderFactory.get(&quot;job&quot;)
                                     .start(step())
                                     ,build();
     }

     public static void main(String[] args) {
         SpringApplication.run(HelloWorldApplication.class, args);
     }
 }</code></pre>
<p><strong>@EnableBatchProcessing</strong> 애너테이션을 사용함으로써 다음과 같은 컴포넌트를 직접 포함시킬 필요가 없어진다.</p>
<ul>
<li>JobRepository : 실행 중인 잡의 상태를 기록하는 데 사용됨</li>
<li>JobLauncher : 잡을 구동하는 데 사용됨</li>
<li>JobExplorer : JobRepository를 사용해 읽기 전용 작업을 수행하는 데 사용됨</li>
<li>JobRegistry : 특정한 런저 구현체를 사용할 때 잡을 찾는 용도로 사용됨</li>
<li>PlatformTransactionManager : 잡 진행 과정에서 트랜잭션을 다루는 데 사용됨</li>
<li>JobBuilderFactory : 잡을 생성하는 빌더</li>
<li>StepBuilderFactory : 스텝을 생성하는 빌더</li>
</ul>
<p><strong>@SpringBootApplication</strong> 애너테이션은 @ComponentScan + @EnableAutoConfiguration 을 결합한 메타 애너테이션이다. 데이터 소스 뿐만 아니라 스프링 부트 기반의 적절한 자동 구성을 만들어 준다.</p>
<p>클래스 정의가 끝난 이후에, 스프링 배치가 제공하는 두 개의 빌더(잡 빌더, 스텝 빌더)를 자동 와이어링 한다. 각 빌더는 @EnableBatchProcessing</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[3. 연결리스트(Linked List) - 구현]]></title>
            <link>https://velog.io/@0_0ni/3.-%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B8Linked-List-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@0_0ni/3.-%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B8Linked-List-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Sat, 04 Mar 2023 09:00:56 GMT</pubDate>
            <description><![CDATA[<ul>
<li>자바스크립트 기준 </li>
</ul>
<blockquote>
<p><strong>추상자료형</strong>
추상자료형은 어떠한 데이터와 그 데이터에 대한 연산을 표기하는 것
ex) 세탁기로 옷을 세탁하는 과정
여기서 옷이 &#39;어떠한 데이터&#39;이며, 세탁기에는 이 옷(데이터)을 처리하는 여러 가지 기능(연산)이 있는데 세탁 / 탈수 / 남은시간 / 배수 등이 있다.
이처럼 데이터와 그 데이터를 연산하는 기능을 표기하는 것을 추상자료형이라고 한다.</p>
</blockquote>
<h3 id="연결리스트의-추상자료형">연결리스트의 추상자료형</h3>
<ul>
<li>연결리스트에 필요한 연산을 대충 추리자면 아래와 같다.
(1) 모든 데이터 출력 -&gt; printAll()
(2) 모든 데이터 제거 -&gt; clear()
(3) 인덱스에 데이터 삽입 -&gt; insertAt(index, data);
(4) 마지막 데이터 뒤에 데이터 삽입 -&gt; insertLast(data);
(5) 원하는 인덱스의 데이터 삭제 -&gt; deleteAt(index);
(6) 마지막 데이터 제거 -&gt; deleteLast();
(7) 원하는 인덱스에 있는 데이터 읽기 -&gt;  getNodeAt(index);</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2. 연결리스트 - 개념]]></title>
            <link>https://velog.io/@0_0ni/2.-%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@0_0ni/2.-%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EA%B0%9C%EB%85%90</guid>
            <pubDate>Sat, 04 Mar 2023 08:41:03 GMT</pubDate>
            <description><![CDATA[<p>배열의 경우, 연속된 메모리 공간이 필요하다는 단점이 있었다.
이를 해결하기 위해서는 데이터를 분산 저장한 후, 이를 서로 연결해주면 될 것이다.
이 때 <strong>노드(Node)</strong>를 만들어 사용하게 되는데, 노드는 데이터를 담는 변수 하나와 다음 노드를 가리키는 변수 하나를 가지고 있다. </p>
<p><img src="https://velog.velcdn.com/images/0_0ni/post/a7498e2f-0964-4f97-8ff7-a7e501a801e7/image.png" alt=""></p>
<p>위와 같은 구조를 <strong>연결리스트</strong>라고 한다.
연결리스트는 첫 노드의 주소만 알고 있으면 다른 모든 노드에 접근이 가능하다.</p>
<h3 id="연결리스트">연결리스트</h3>
<p>연결리스트의 경우, 배열과 달리 빈 메모리 공간 아무 곳에나 데이터를 생성한 뒤, 그것을 연결만 해주면 되기 때문에 <strong>배열의 초기 크기를 가늠할 필요가 없다.</strong></p>
<p>배열의 경우 중간에 데이터를 삽입하면, 이후의 값들이 모두 뒤로 밀리기 때문에 오버헤드가 많이 든다. 반면 연결리스트는 <strong>중간에 데이터를 삽입하더라도 다음에 가리키는 노드만 바꿔주면 되기 때문에 비교적 간단하다.</strong></p>
<p>배열은 메모리의 연속된 공간에 할당되어 있어 시작 주소만 알고 있다면 그 이후의 데이터에 접근하는 것이 용이하다. O(1)의 성능을 갖는다.
반면 연결리스트의 경우 <strong>데이터가 떨어져 있으므로 다음 데이터까지의 접근이 용이하지 않다.</strong> 노드를 계속 타며 원하는 데이터에 접근해야 하므로 O(n)의 성능을 갖는다. </p>
<h3 id="배열과-연결리스트-비교">배열과 연결리스트 비교</h3>
<ul>
<li>크기 : 배열은 크기 고정 / 연결리스트는 필요에 따라 동적인 크기의 배열 사용 가능</li>
<li>주소 : 배열은 연속된 메모리 공간에 값 할당 / 연결리스트는 불연속적인 메모리 공간에 값 할당한 후 노드를 이용해 그를 연결</li>
<li>데이터 참조 : 배열은 메모리의 연속된 공간에 할당되기 때문에 메모리 접근이 굉장히 빠르다. O(1)의 성능 / 연결리스트는 데이터 참조를 위해 앞에서부터 해당 노드까지 접근해야 하기 때문에 배열에 비해 느리다. O(n)의 성능 </li>
<li>삽입과 삭제 : 배열에서 데이터를 삽입하려면 기존 모든 데이터를 옮겨야 하므로 O(n)의 성능을 갖는다. / 연결리스트는 데이터의 삽입 혹은 삭제를 위해 원하는 위치까지 노드를 타며 이동해야 하므로 O(n)의 성능을 갖는다. </li>
</ul>
<p><img src="https://velog.velcdn.com/images/0_0ni/post/fb6f3647-2af4-4eb9-be04-2ef3084526e9/image.png" alt=""></p>
<p>데이터의 변경은 잘 일어나지 않고, 잦은 참조를 해야 한다면 =&gt; 배열
데이터의 삽입 및 삭제가 빈번할 경우 =&gt; 연결리스트</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1. 배열]]></title>
            <link>https://velog.io/@0_0ni/1.-%EB%B0%B0%EC%97%B4</link>
            <guid>https://velog.io/@0_0ni/1.-%EB%B0%B0%EC%97%B4</guid>
            <pubDate>Sat, 04 Mar 2023 08:23:07 GMT</pubDate>
            <description><![CDATA[<h3 id="배열">배열</h3>
<p>모든 프로그래밍 언어에서 제공하는 자료구조.</p>
<p>일반적으로 int arr[10] = {1,2,3,4,5}; 라는 배열을 지정했을 경우,
운영체제는 메모리에서 숫자 10개가 들어갈 수 있는 빈 공간을 찾아서 순서대로 값을 할당한다. 값이 할당되지 않은 빈 공간에는 쓰레기 값이 저장된다.
운영체제는 첫번째 값이 들어간 <strong>배열의 시작주소</strong>만 기억하는데, 프로그래머가 배열의 세 번째 원소에 접근하고 싶다면 arr[2] 와 같이 <strong>인덱스</strong>를 이용해 한 번에 접근한다. </p>
<h3 id="배열의-인덱스-참조">배열의 인덱스 참조</h3>
<p>배열의 길이와 상관없이 한 번에 가져오기 때문에 <strong>O(1)</strong> 의 성능을 갖는다.
때문에 배열은 <strong>읽기/쓰기</strong>, 즉 참조에서 좋은 성능을 보인다.
그러나 <strong>데이터의 삽입, 삭제 성능은 좋지 않음.</strong> </p>
<p>예를 들어, 프로그래머가 길이가 10인 배열을 생성한 뒤, 이 배열의 길이를 15로 늘리고 싶다면 운영체제는 길이가 15인 배열이 들어갈 수 있는 빈 공간을 다시 탐색하고, 또한 기존의 배열에 저장되어 있던 값을 복사해야 함. </p>
<p>자바스크립트의 경우 초기 배열 생성 당시 길이를 지정하지 않는다.
자바스크립트에서 배열은 상황에 따라서 연속적, 불연속적으로 메모리를 할당하지만, 대부분은 불연속적으로 할당한다. 이를 내부적으로 연결해 사용자에게는 배열인 것 처럼 보이는 것.</p>
<h3 id="배열의-장단점">배열의 장단점</h3>
<ul>
<li>장점 : 읽기, 쓰기와 같은 참조에는 O(1)의 성능을 갖는다.</li>
<li>단점 : 크기 예측이 힘들기 때문에 메모리 낭비가 발생할 수 있다.<pre><code>  데이터의 삽입, 삭제가 비효율적이다.</code></pre></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Shell Script 파일 체크]]></title>
            <link>https://velog.io/@0_0ni/Shell-Script-%ED%8C%8C%EC%9D%BC-%EC%B2%B4%ED%81%AC</link>
            <guid>https://velog.io/@0_0ni/Shell-Script-%ED%8C%8C%EC%9D%BC-%EC%B2%B4%ED%81%AC</guid>
            <pubDate>Fri, 03 Mar 2023 06:04:07 GMT</pubDate>
            <description><![CDATA[<h3 id="기본-문법">기본 문법</h3>
<pre><code class="language-sh">if [ -f &quot;$FILENAME&quot; ]; then
    echo &quot;file exist&quot;
else 
    echo &quot;file not exist&quot;
fi</code></pre>
<h3 id="옵션">옵션</h3>
<ul>
<li>-b FILE
  파일이 존재하고 특별한 파일인지 체크
  FILE exists and is block special</li>
<li>-c FILE
  파일이 존재하고 특수문자가 있는지 체크
  FILE exists and is character special</li>
<li><strong>-d FILE ; 디렉토리 여부 확인</strong>
  파일이 존재하고 그 파일이 폴더인지 체크
  FILE exists and is a directory</li>
<li><strong>-e FILE ; 파일과 폴더 구분 없이 존재하는지 확인</strong>
  파일이 존재하는지 체크
  FILE exists</li>
<li><strong>-f FILE ; 파일 유무 및 보통 파일 확인</strong>
  파일이 존재하고 보통 파일인지 체크
  FILE exists abd is a reqular file</li>
<li>-g FILE
  파일이 존재하고 group ID로 설정되었는지 체크
  FILE exixsts and is set-group-ID</li>
<li>-G FILE
  FILE exists and is owned by the effective group ID </li>
<li>-h FILE
  파일이 존재하고 symbolic link 파일인지 확인
  FILE exists and is a symbolic link (same as -L)</li>
<li>-k FILE
  FILE exists and has its sticky bit set</li>
<li>-L FILE
  파일이 존재하고 symbolic link 파일인지 확인
  FILE exists and is a symbolic link (same as -h)</li>
<li>-O FILE
  파일이 존재하고 owner가 유효한지 확인
  FILE exists and is owned by the effective user ID</li>
<li>-p FILE
  파일이 존재하고 그 파일이 pipe인지 확인
  FILE exists and is a named pipe</li>
<li>-r FILE
  파일이 존재하고 read 가능한 파일인지 확인
  FILE exists and read permission is granted</li>
<li>-s FILE
  파일이 존재하고 0 size 파일이 아닌지 체크
  FILE is exists and has a size greater than zero</li>
<li>-S FILE
  파일이 존재하고 그 파일이 소켓인지 확인
  FILE eixsts and is a socket</li>
<li>-t FD file descriptor FD is opened on a ternimal</li>
<li>-u FILE
  FILE exists and its set-user-ID bit is set</li>
<li>-w FILE
  파일이 존재하고 쓰기 가능한 파일인지 확인
  FILE exists and write permission is granted</li>
<li>-x FILE
  파일이 존재하고 실행 가능한 파일인지 확인
  FILE exists and execute (or search) permission is granted</li>
</ul>
<p>참고: <a href="https://foris.tistory.com/256">https://foris.tistory.com/256</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[String] 가장 짧은 문자거리]]></title>
            <link>https://velog.io/@0_0ni/String-%EA%B0%80%EC%9E%A5-%EC%A7%A7%EC%9D%80-%EB%AC%B8%EC%9E%90%EA%B1%B0%EB%A6%AC</link>
            <guid>https://velog.io/@0_0ni/String-%EA%B0%80%EC%9E%A5-%EC%A7%A7%EC%9D%80-%EB%AC%B8%EC%9E%90%EA%B1%B0%EB%A6%AC</guid>
            <pubDate>Mon, 27 Feb 2023 03:45:46 GMT</pubDate>
            <description><![CDATA[<h3 id="가장-짧은-문자거리">가장 짧은 문자거리</h3>
<p>한 개의 문자열 s와 문자 t가 주어졌을 때, 문자열 s의 각 문자가 문자 t와 떨어진 최소거리를 출력하는 프로그램을 작성하세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>첫 번째 줄에 문자열 s와 문자 t가 주어진다. 문자열과 문자는 소문자로만 주어진다.
문자열의 길이는 100을 넘지 않는다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<h4 id="입력">입력</h4>
<p> teachermode e</p>
<h4 id="출력">출력</h4>
<p> 1 0 1 2 1 0 1 2 2 1 0</p>
<hr>
<h3 id="풀이">풀이</h3>
<p>|---  s --|&gt;|0|1|2|3|4|5|6|7|8|9|10|
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|||t|e|a|c|h|e|r|m|o|d|e|</p>
<p>|answer|&gt;|0|1|2|3|4|5|6|7|8|9|10|
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|||t|e|a|c|h|e|r|m|o|d|e|</p>
<hr>
<h3 id="구현">구현</h3>
<pre><code class="language-java"> import java.util.*;
 class Main {





    public static void main(String[] args) {
        Main T = new Main();
        Scanner kb = new Scanner(System.in);
        String str = kb.next();
        System.out.print(T.solution(str));
    }
 }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[String] 숫자만 추출]]></title>
            <link>https://velog.io/@0_0ni/String-%EC%88%AB%EC%9E%90%EB%A7%8C-%EC%B6%94%EC%B6%9C</link>
            <guid>https://velog.io/@0_0ni/String-%EC%88%AB%EC%9E%90%EB%A7%8C-%EC%B6%94%EC%B6%9C</guid>
            <pubDate>Mon, 27 Feb 2023 03:05:12 GMT</pubDate>
            <description><![CDATA[<h3 id="숫자만-추출">숫자만 추출</h3>
<p>문자와 숫자가 섞여있는 문자열이 주어지면 그 중 숫자만 추출하여 그 순서대로 자연수를 만듭니다. 
만약 &quot;tgeDa1h205er&quot;에서 숫자만 추출한다면 0, 1, 2, 0, 5 이고, 이것을 자연수로 만들면 1205가 됩니다. 추출하여 만들어지는 자연수는 100,000,000을 넘지 않습니다.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>첫 줄에 숫자가 섞인 문자열이 주어집니다. 문자열의 길이는 100을 넘지 않습니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<h4 id="입력">입력</h4>
<p> g0en2T0s8eSoft</p>
<h4 id="출력">출력</h4>
<p> 208</p>
<hr>
<h3 id="풀이">풀이</h3>
<p> 숫자만 골라내야 하는데, 0~9의 아스키 코드 값은 48 ~ 57임.
 x &gt;= 48 &amp;&amp; x &lt;= 57 을 만족하는 경우, 숫자로 판단.</p>
<p> &quot;tge<strong>0</strong>Da<strong>1</strong>h<strong>205</strong>er&quot;</p>
<ul>
<li><p>0 (Ascii 48)
answer 의 초기값이 0일 때, x는 48이므로
answer = answer * 10 + (x-48);
0 = 0 x 10 + (48-48); ====&gt; 0</p>
</li>
<li><p>1 (Ascii 49)
1 = 0 x 10 + (49-48); ====&gt; 1</p>
</li>
<li><p>2 (Ascii 49)
12 = 1 x 10 + (50-48); ====&gt; 2</p>
</li>
<li><p>0 (Ascii 48)
120 = 12 x 10 + (48-48); ====&gt; 120</p>
</li>
<li><p>5 (Ascii 49)
1205 = 120 x 10 + (53-48); ====&gt; 1205</p>
</li>
</ul>
<hr>
<h3 id="구현">구현</h3>
<pre><code class="language-java"> import java.util.*;
 class Main {

     // (1)
     public int solution(String s) {
        int answer = 0;

        for(char x : s.toCharArray()) {
            if (x&gt;= 48 &amp;&amp; x &lt;= 57) answer = answer * 10 + (x-48);
        }

        return answer;
    }

    // (2)
     public int solution(String s) {
        String answer = &quot;&quot;;

        for(char x : s.toCharArray()) {
            // isDigit() : 숫자 판별 함수
            if (Character.isDigit(x)) answer += x;
        } // 여기까지만 하면 answer는 String이므로 &quot;0208&quot; 출력됨.

        return Integer.parseInt(answer); // int로 파싱.
    }


    public static void main(String[] args) {
        Main T = new Main();
        Scanner kb = new Scanner(System.in);
        String str = kb.next();
        System.out.print(T.solution(str));
    }
 }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[String] 팰린드롬(replaceAll 정규식이용)]]></title>
            <link>https://velog.io/@0_0ni/String-%ED%8C%B0%EB%A6%B0%EB%93%9C%EB%A1%ACreplaceAll-%EC%A0%95%EA%B7%9C%EC%8B%9D%EC%9D%B4%EC%9A%A9</link>
            <guid>https://velog.io/@0_0ni/String-%ED%8C%B0%EB%A6%B0%EB%93%9C%EB%A1%ACreplaceAll-%EC%A0%95%EA%B7%9C%EC%8B%9D%EC%9D%B4%EC%9A%A9</guid>
            <pubDate>Mon, 27 Feb 2023 03:02:39 GMT</pubDate>
            <description><![CDATA[<h3 id="유효한-팰린드롬">유효한 팰린드롬</h3>
<p>앞에서 읽을 때나 뒤에서 읽을 때나 같은 문자열을 팰린드롬이라고 합니다.
문자열이 입력되었을 때, 해당 문자열이 팰린드롬이면 &quot;YES&quot;, 아니면 &quot;NO&quot;를 출력하는 프로그램을 작성하세요. 단 회문을 검사할 때 알파벳만 가지고 회문을 검사하며, 대소문자를 구분하지 않습니다. 알파벳 이외의 문자는 무시합니다.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>첫 줄에 길이 100을 넘지 않는 공백이 없는 문자열이 주어집니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<h4 id="입력">입력</h4>
<p> found7, time: study; Yduts; emit, 7Dnuof</p>
<h4 id="출력">출력</h4>
<p> YES</p>
<hr>
<h3 id="구현">구현</h3>
<pre><code class="language-java"> import java.util.*;
 class Main {
     public String solution(String s) {
        String answer = &quot;NO&quot;;
        // replace()는 정규식 사용불가, replaceAll()은 정규식 사용 가능
        s = s.toUpperCase().replaceAll(&quot;[^A-Z]&quot;, &quot;&quot;); //A-Z를 제외한 나머지 문자 처리
        String tmp = new StringBuilder(s).reverse().toString();

        if ( s.equals(tmp) ) answer = &quot;YES&quot;;

        return answer;
    }


    public static void main(String[] args) {
        Main T = new Main();
        Scanner kb = new Scanner(System.in);
        String str = kb.next();
        System.out.print(T.solution(str));
    }
 }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[String] 회문문자열(palindrome)]]></title>
            <link>https://velog.io/@0_0ni/String-%ED%9A%8C%EB%AC%B8%EB%AC%B8%EC%9E%90%EC%97%B4palindrome</link>
            <guid>https://velog.io/@0_0ni/String-%ED%9A%8C%EB%AC%B8%EB%AC%B8%EC%9E%90%EC%97%B4palindrome</guid>
            <pubDate>Mon, 27 Feb 2023 02:41:56 GMT</pubDate>
            <description><![CDATA[<h3 id="회문문자열">회문문자열</h3>
<p>앞에서 읽을 때나 뒤에서 읽을 때나 같은 문자열을 회문 문자열이라고 합니다.
문자열이 입력될 때, 해당 문자열이 회문 문자열이면 &quot;YES&quot;, 회문 문자열이 아니면 &quot;NO&quot;를 출력하는 프로그램을 작성하세요.
단, 회문을 검사할 때 대소문자를 구분하지 않습니다.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>첫 줄에 길이 100을 넘지 않는 공백이 없는 문자열이 주어집니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<h4 id="입력">입력</h4>
<p> gooG</p>
<h4 id="출력">출력</h4>
<p> YES</p>
<hr>
<h3 id="풀이">풀이</h3>
<p> 문자열의 절반까지 돌면서 같은 문자열 찾기.
 len/2 ---&gt; i &lt; len/2
 대소문자 구분 없으므로 대문자 혹은 소문자로 통일 후 비교</p>
<table>
<thead>
<tr>
<th align="left"></th>
<th align="left"></th>
<th align="left"></th>
<th align="left"></th>
</tr>
</thead>
<tbody><tr>
<td align="left">0</td>
<td align="left">1</td>
<td align="left">2</td>
<td align="left">3</td>
</tr>
<tr>
<td align="left">G</td>
<td align="left">O</td>
<td align="left">O</td>
<td align="left">G</td>
</tr>
<tr>
<td align="left">i</td>
<td align="left"></td>
<td align="left"></td>
<td align="left">len-i-1</td>
</tr>
</tbody></table>
<hr>
<h3 id="구현">구현</h3>
<pre><code class="language-java"> import java.util.*;
 class Main {
     /// (1)
     public String solution(String str) {
        String answer = &quot;YES&quot;;
        str = str.toUpperCase();
        int len = str.length();

        for (int i=0; i &lt; len/2; i++) {
            if(str.charAt(i) != str.charAt(len-i-1)) return &quot;NO&quot;;
        }

        return answer;
    }

    /// (2)
    public String solution(String str) {
        String answer = &quot;NO&quot;;
        String tmp = new StringBuilder(str).reverse().toString();

        // equals는 대소문자 구분하므로 IgnoreCase 추가해야 함.
        if ( str.equalsIgnoreCase(tmp) ) answer = &quot;YES&quot;;

        return answer;
    }

    public static void main(String[] args) {
        Main T = new Main();
        Scanner kb = new Scanner(System.in);
        String str = kb.next();
        System.out.print(T.solution(str));
    }
 }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[String] 중복문자제거 (indexOf())]]></title>
            <link>https://velog.io/@0_0ni/String-%EC%A4%91%EB%B3%B5%EB%AC%B8%EC%9E%90%EC%A0%9C%EA%B1%B0-indexOf</link>
            <guid>https://velog.io/@0_0ni/String-%EC%A4%91%EB%B3%B5%EB%AC%B8%EC%9E%90%EC%A0%9C%EA%B1%B0-indexOf</guid>
            <pubDate>Wed, 22 Feb 2023 03:14:37 GMT</pubDate>
            <description><![CDATA[<h3 id="중복-문자-제거">중복 문자 제거</h3>
<p>소문자로 된 한 개의 문자열이 입력되면 중복된 문자를 제거하고 출력하는 프로그램을 작성하세요.
중복이 제거된 문자열의 각 문자는 원래 문자열의 순서를 유지합니다.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>첫 줄에 문자열이 입력됩니다. 문자열의 길이는 100을 넘지 않습니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<h4 id="입력">입력</h4>
<p> ksekkset</p>
<h4 id="출력">출력</h4>
<p> kset</p>
<hr>
<h3 id="구현">구현</h3>
<pre><code class="language-java">import java.util.*;
class Main {
    public String solution(String str) {
        String answer = &quot;&quot;;

        for (int i=0; i &lt; str.length(); i++) {
            //System.out.println(str.charAt(i) + &quot; &quot; + i + &quot; &quot; + str.indexOf(str.charAt(i)));
            if (str.indexOf(str.charAt(i)) == i) answer += str.charAt(i);
        }
        return answer;
    }

    public static void main(String[] args) {
        Main T = new Main();
        Scanner kb = new Scanner(System.in);
        String str = kb.next();
        System.out.println(T.solution(str));
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[String] 특정 문자 뒤집기(toCharArray())]]></title>
            <link>https://velog.io/@0_0ni/Java-%ED%8A%B9%EC%A0%95-%EB%AC%B8%EC%9E%90-%EB%92%A4%EC%A7%91%EA%B8%B0toCharArray</link>
            <guid>https://velog.io/@0_0ni/Java-%ED%8A%B9%EC%A0%95-%EB%AC%B8%EC%9E%90-%EB%92%A4%EC%A7%91%EA%B8%B0toCharArray</guid>
            <pubDate>Wed, 22 Feb 2023 02:54:20 GMT</pubDate>
            <description><![CDATA[<h3 id="특정-문자-뒤집기">특정 문자 뒤집기</h3>
<p>영어 알파벳과 특수문자로 구성된 문자열이 주어지면 영어 알파벳만 뒤집고,
특수문자는 자기 자리에 그대로 있는 문자열을 만들어 출력하는 프로그램을 작성하세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>첫 줄에 길이가 100을 넘지 않는 문자열이 주어집니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<h4 id="입력">입력</h4>
<p> a#b!GE*T@S</p>
<h4 id="출력">출력</h4>
<p> S#T!EF*b@a</p>
<hr>
<h3 id="구현">구현</h3>
<pre><code class="language-java">import java.util.*;
class Main {
    public String solution(String str) {
        String answer;
        char[] s = str.toCharArray();
        int lt = 0, rt = str.length()-1;
        while(lt&lt;rt) {
            if ( !Character.isAlphabetic(s[lt]) ) lt++;
            else if ( !Character.isAlphabetic(s[rt]) ) rt--;
            else {
                char tmp = s[lt];
                s[lt] = s[rt];
                s[rt] = tmp;
                lt++;
                rt--;
            }
        }
        answer = String.valueOf(s);

        return answer;
    }

    public static void main(String[] args) {
        Main T = new Main();
        Scanner kb = new Scanner(System.in);
        String str = kb.next();
        System.out.println(T.solution(str));
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[package ~ does not exist error]]></title>
            <link>https://velog.io/@0_0ni/package-does-not-exist-error</link>
            <guid>https://velog.io/@0_0ni/package-does-not-exist-error</guid>
            <pubDate>Tue, 14 Feb 2023 00:46:30 GMT</pubDate>
            <description><![CDATA[<p>pom.xml에 dependency가 추가되어 있음에도 불구하고, 
인텔리제이에서 계속 컴파일 오류가 발생</p>
<p>package org.apache.commons.vfs2 does not exist</p>
<p><strong>pom.xml 우클릭 &gt; Maven &gt; Reload project</strong> 하니 해결되었다.
이는 pom.xml을 프로젝트 유형으로 여는 것과 완전히 동일한 기능이라고 함.
그래서 해당 기능 실행한 이후에는 &quot;Web Resource Directory&quot; 경로 재설정 필요하다고 한다.</p>
<p>위와 같이 해결이 된 상황 이후에도 Project Structure &gt; Library 가면 해당 패키지 항목이 보이지 않는다. 여기서도 보이려면 인텔리제이 재시작이 필요함.</p>
<p>참고 : <a href="https://www.sysnet.pe.kr/2/0/12761">https://www.sysnet.pe.kr/2/0/12761</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] Enum 정의와 활용]]></title>
            <link>https://velog.io/@0_0ni/Java-Enum-%EC%A0%95%EC%9D%98%EC%99%80-%ED%99%9C%EC%9A%A9</link>
            <guid>https://velog.io/@0_0ni/Java-Enum-%EC%A0%95%EC%9D%98%EC%99%80-%ED%99%9C%EC%9A%A9</guid>
            <pubDate>Mon, 06 Feb 2023 01:41:55 GMT</pubDate>
            <description><![CDATA[<h3 id="enum이란">Enum이란</h3>
<blockquote>
<p>Enum이란 Enumeration의 앞 글자를 딴 약어로, <strong>열거</strong>라는 의미이다. 서로 관련있는 상수들을 모아서 대표 이름으로 클래스를 정의하고 활용하는 데에 사용된다.</p>
</blockquote>
<hr>
<h3 id="내부구현">내부구현</h3>
<p>가장 기본적이고 간단한 Enum 타입을 통해 내부 구현 형태를 알아보자. <code>Direction</code>이라는 Enum 클래스가 아래와 같이 정의되어 있다고 하자.</p>
<pre><code class="language-java">enum Direction { EAST, WEST, SOUTH, NORTH }</code></pre>
<p>동서남북을 값으로 갖는 이 클래스는, 내부적으로 아래와 같이 구현된다.</p>
<pre><code class="language-java">enum Direction {

    static final Direction EAST = new Direction(&quot;EAST&quot;);
    static final Direction WEST = new Direction(&quot;WEST&quot;);
    static final Direction SOUTH = new Direction(&quot;SOUTH&quot;);
    static final Direction NORTH = new Direction(&quot;NORTH&quot;);

    private String name;

    private Direction(String name) { this.name = name; }   
}</code></pre>
<p>Default 필드로 <code>name</code>이 생성되고, Default 생성자로는 <code>name</code>을 할당하는 생성자가 구현된다. </p>
<p>Default 생성자의 접근제어자는 묵시적으로 <code>private</code>이며, <code>public</code>일 수 없다. 외부에서 Enum 상수에 접근하려면 생성자가 아니라, <code>Direction.EAST</code>와 같은 형식으로 접근해야 한다.</p>
<hr>
<h3 id="api">API</h3>
<p>Enum 클래스는 기본적으로 몇 가지 메서드를 제공한다.</p>
<h4 id="instance-method">Instance Method</h4>
<ul>
<li><code>int ordinal()</code>
Enum 클래스 안에서 상수의 Index를 반환한다. Index는 선언된 순서대로 0부터 시작한다.</li>
<li><code>String name()</code>, <code>String toString()</code>
Enum 클래스 안에서 상수의 이름을 반환한다.</li>
</ul>
<h4 id="static-method">Static Method</h4>
<ul>
<li><p><code>Enum&lt;T&gt;[] values()</code>
Enum 클래스에 있는 모든 상수값을 배열로 반환한다. <code>String[]</code>이 아니라, Enum 클래스 타입의 <strong>객체</strong>로 반환하는 것이다.</p>
</li>
<li><p><code>Enum&lt;T&gt; valueOf(String name)</code>
Enum 클래스 안에서 인자로 들어온 <code>name</code>과 같은 상수가 있으면, 그 상수 <strong>객체</strong>를 반환한다.</p>
</li>
</ul>
<hr>
<h3 id="활용">활용</h3>
<p>두 Enum 객체의 값을 비교하여 Index 비교 결과를 반환하는 메서드가 내부적으로 구현되어 있다.</p>
<ul>
<li><code>int compareTo(E o)</code></li>
<li><code>boolean equals(Object other)</code></li>
</ul>
<p>두 메서드 모두 기본적으로 Enum 클래스 안에서 <strong>선언된 순서</strong>를 비교하여 결과를 산출한다.</p>
<blockquote>
<p>💡 같은 Enum Type 객체들 간 비교는 <code>==</code> 연산자로도 가능하다. <code>equals()</code>를 사용해도 내부적으로 <code>==</code> 연산자를 호출하기 때문에, <code>==</code> 를 사용해서 비교하는 것이 더 효율적이다. 하지만 <code>&gt;</code>, <code>&lt;</code>와 같은 연산자 비교는 불가능하다.</p>
</blockquote>
<h3 id="additional-field">Additional Field</h3>
<p>Enum 상수들은 <code>name</code> 말고도 다른 값들을 필드로 가질 수 있다.</p>
<pre><code class="language-java">enum Direction {

    EAST(1, &quot;&gt;&quot;);
    WEST(5, &quot;V&quot;);
    SOUTH(-1, &quot;&lt;&quot;);
    NORTH(10, &quot;^&quot;);

    private final int value;
    private final String symbol;

    Direction(int value, String symbol) {
        this.value = value;
        this.symbol = symbol;
    }

    private int getValue() { return value; }
    private String getSymbol() { return symbol; }
}</code></pre>
<h3 id="다형성">다형성</h3>
<p>Enum 클래스에 추상 메서드를 선언하고, 상수마다 추상 메서드를 구현하여 다형성을 구현할 수 있다.</p>
<h4 id="abstract-method">Abstract Method</h4>
<p>Enum 클래스 안에 추상 메서드를 선언하면, 각 상수들은 그 메서드를 오버라이딩 해야 한다. 이를 통해 같은 기능을 상수마다 다르게 구현할 수 있다.</p>
<pre><code class="language-java">enum Transportation {

    BUS(100) { int fare(int distance) { return distance * basicFare; }},
    TRAIN(150) { int fare(int distance) { return distance * basicFare; }},
    AIRPLAIN(300) { int fare(int distance) { return distance * basicFare; }};  

    abstract int fare(int distance);

    protected final int basicFare;

    Transportation(int basicFare) { basicFARE; }

    pubic int getBasicFare() { return basicFare; }
}</code></pre>
<p>근데 Body 자체를 다 적어줘야 하다보니 코드가 지저분해진다. 그럴 때 사용할 수 있는 것이 아래의 Lamda다.</p>
<h4 id="lamda">Lamda</h4>
<p>아래는 Functional Interface와 Lamda를 활용해 Enum 클래스에서 기능을 구현한 것이다.</p>
<pre><code class="language-java">import java.util.function.DoubleBinaryOperator;

enum Operator {

    PLUS((a, b) -&gt; a * b),
    MINUS((a, b) -&gt; (a - b)),
    MULTIPLY((a, b) -&gt; ( a * b)),
    DIVIDE((a, b) -&gt; ( a / b));

    private final DoubleBinaryOperator doubleBinaryOperator;

    Operator(DoubleBinaryOperator doubleBinaryOperator) {
        this.doubleBinaryOperator = doubleBinaryOperator;
    }

    public Double caculate(double a, double b) {
        return this.doubleBinaryOperator.applyAsDouble(a, b);
    }
}</code></pre>
<p>이 <code>Operator</code> 클래스는 외부에서 아래와 같이 사용할 수 있다.</p>
<pre><code class="language-java">Operator.PLUS.calculate(1, 2);      // 3.0
Operator.MINUS.calculate(1, 2);     // -1.0
Operator.MULTIPLY.calculate(1, 2);  // 2.0
Operator.DIVIDE.calculate(1, 2);    // 0.5</code></pre>
<h3 id="기능구현">기능구현</h3>
<p>Enum 클래스 내부에 상수들과 연관 있는 기능들을 구현하여 효율적으로 관리할 수 있다.</p>
<pre><code class="language-java">enum Statistic {

    THREE(3, 5000),
    FOUR(4, 50_000),
    FIVE(5, 1_500_000),
    BONUS(5, 3_000_000),
    SIX(6, 2_000_000_000);

    private final int matchingNumbers;
    private final int prize;

    Statistic(int matchingNumbers, int prize) {
        this.matchingNumbers = matchingNumbers;
        this.prize = prize;
    }

    public static Statistic getRank(int numberOfMatch) {
        return Arrays.stream(values())
                .filter(statistic -&gt; statistic.matchingNumbers == numberOfMatch)
                .findFirst()
                .orElseThrow();
    }
}</code></pre>
<hr>
<p>참고 : <a href="https://velog.io/@jwkim/java-enum">Enum 정의와 활용</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[재귀 - 팩토리얼(Factorial)]]></title>
            <link>https://velog.io/@0_0ni/%EC%9E%AC%EA%B7%80-%ED%8C%A9%ED%86%A0%EB%A6%AC%EC%96%BCFactorial</link>
            <guid>https://velog.io/@0_0ni/%EC%9E%AC%EA%B7%80-%ED%8C%A9%ED%86%A0%EB%A6%AC%EC%96%BCFactorial</guid>
            <pubDate>Fri, 03 Feb 2023 03:25:32 GMT</pubDate>
            <description><![CDATA[<h3 id="재귀함수란">재귀함수란?</h3>
<p>함수 내에서 자기 자신(함수)을 계속적으로 호출 하면서 풀어가는 방식.
함수가 호출 되면서 최근에 자신을 불렀던 기존 함수가 스택에 차곡차곡 쌓이게 된다.</p>
<p><strong>처음 호출된 함수(스택 맨 밑에 있는 메소드)에서 return 되는 값이 최종 return 값이 된다.</strong></p>
<hr>
<h3 id="팩토리얼이란">팩토리얼이란?</h3>
<p>3! = <code>3*2*1</code> = 6
4! = <code>4*3*2*1</code> = 24
5! = <code>5*4*3*2*1</code> = 120</p>
<hr>
<h3 id="문제">문제</h3>
<h4 id="재귀를-이용한-특정-숫자의-팩토리얼-연산">재귀를 이용한 특정 숫자의 팩토리얼 연산</h4>
<pre><code class="language-java">public class Factorial {

    public static void main(String[] args) {
        int input = 4;   // 4!

        System.out.println(fact(input));
    }

    public static int fact(int n) {
        if ( n &lt;= 1 ) 
             return n;
        else 
             return fact(n-1)*n;  
    }
}</code></pre>
<h4 id="결과">결과</h4>
<blockquote>
<p>24</p>
</blockquote>
<hr>
<h3 id="설명">설명</h3>
<p>1) 처음 fact 메소드가 호출된 것은 main 함수에서이다. fact(4)가 실행된다.</p>
<p>2) <strong>fact(4)</strong>
n은 현재 4이다. n은 1보다 크므로 else를 타고, fact(3)이 호출된다.</p>
<p>3) 여기서 처음 호출된 fact(4)는 종료되지 않고 Stack에 쌓인 상태로, fact(4)가 호출한 fact(3)이 실행된다.</p>
<blockquote>
<p><strong>Stack</strong>
<code>fact(4)</code></p>
</blockquote>
<p>4) <strong>fact(3)</strong>
n은 현재 3이다. n은 1보다 크므로 else를 타고, fact(2)가 호출된다.</p>
<blockquote>
<p><strong>Stack</strong>
<code>fact(3)</code>
<code>fact(4)</code></p>
</blockquote>
<p>5) 이 때 호출된 fact(3) 또한 종료되지 않은 상태로 Stack에 쌓이고, fact(3)이 호출한 fact(2)이 실행된다.</p>
<p>6) <strong>fact(2)</strong>
n은 현재 2이다. n은 1보다 크므로 else를 타고,
fact(1)이 호출된다.</p>
<p>7) 세번째로 호출된 fact(2)는 종료되지 않은 상태로 Stack에 쌓이고 fact(2)가 호출한 fact(1)이 실행된다.</p>
<blockquote>
<p><strong>Stack</strong>
<code>fact(2)</code>
<code>fact(3)</code>
<code>fact(4)</code></p>
</blockquote>
<p>8) <strong>fact(1)</strong>
n은 현재 1이다. n이 1과 같으므로 if문을 타고 n, 즉 <code>1</code>을 return 한다.</p>
<p>9) fact(1)이 종료되면서, Stack의 가장 위에 있는 fact(2)가 실행된다. 8번에서 리턴 받은 값과 n을 곱하며 return 하고 fact(2)가 종료될 것이다.</p>
<p>fact(2) 에서는 n이 2이다.
8) 에서 fact(1)은 1을 리턴했었다.</p>
<p>그래서 fact(2)에서는 1*2 한 값을 return 한다.
 fact(2-1) x n → 1 x 2 </p>
<p>Stack은 이제 아래와 같은 상태가 된다.</p>
<blockquote>
<p><strong>Stack</strong>
<code>fact(3)</code>
<code>fact(4)</code></p>
</blockquote>
<p>이후 같은 과정을 반복하면 <code>1*2*3*4</code>를 연산해 <code>24</code>의 결과값이 나오게 된다.</p>
<p>참고: <a href="https://marobiana.tistory.com/79">https://marobiana.tistory.com/79</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[String] 단어 뒤집기(StringBuilder 사용 혹은 직접 뒤집기)]]></title>
            <link>https://velog.io/@0_0ni/String-%EB%8B%A8%EC%96%B4-%EB%92%A4%EC%A7%91%EA%B8%B0StringBuilder-%EC%82%AC%EC%9A%A9-%ED%98%B9%EC%9D%80-%EC%A7%81%EC%A0%91-%EB%92%A4%EC%A7%91%EA%B8%B0</link>
            <guid>https://velog.io/@0_0ni/String-%EB%8B%A8%EC%96%B4-%EB%92%A4%EC%A7%91%EA%B8%B0StringBuilder-%EC%82%AC%EC%9A%A9-%ED%98%B9%EC%9D%80-%EC%A7%81%EC%A0%91-%EB%92%A4%EC%A7%91%EA%B8%B0</guid>
            <pubDate>Thu, 02 Feb 2023 12:52:36 GMT</pubDate>
            <description><![CDATA[<h3 id="단어-뒤집기">단어 뒤집기</h3>
<p>N개의 단어가 주어지면 각 단어를 뒤집어 출력하는 프로그램을 작성하세요.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>첫 줄에 자연수 N (3 ≤ N ≤ 20) 이 주어집니다.</li>
<li>두 번째 줄 부터 N개의 단어가 각 줄에 하나씩 주어집니다. 단어는 영어 알파벳으로만 구성되어 있습니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<h4 id="입력">입력</h4>
<p> 3
 good
 Time
 Big</p>
<h4 id="출력">출력</h4>
<p> doog
 emiT
 giB</p>
<hr>
<h3 id="구현">구현</h3>
<pre><code class="language-java"> // (1) StringBuilder 사용
import java.util.Scanner;

public class Main {

    public ArrayList&lt;String&gt; solution5(int n, String[] str) {
       ArrayList&lt;String&gt; answer = new ArrayList&lt;&gt;();

       for (String x : str) {
           String temp = new StringBuilder(x).reverse().toString();
        answer.add(temp);
       }

        return answer;
    }

    public static void main(String[] args) {
        Main T = new Main();
        Scanner kb = new Scanner(System.in);
        int n = kb.nextInt();

        String[] str = new String[n];
        for (int i=0; i &lt; n; i++) {
            str[i] = kb.next();
        }
        for (String x : T.solution(n, str)) {
            System.out.println(x);
        }
    }
}

------------------------------------------------------------

 // (2) IndexOf(), substring() 사용
public class Main {

    public ArrayList&lt;String&gt; solution5(int n, String[] str) {
         ArrayList&lt;String&gt; answer = new ArrayList&lt;&gt;();

         for (String x : str) {
             char[] s = x.toCharArray();
            int lt = 0;
            int rt = x.length() - 1;
            while (lt &lt; rt) {
                char temp = s[lt];
                s[lt] = s[rt];
                lt++;
                rt--;
            }
            String temp = String.valueOf(s);
            answer.add(temp);
         }
        return answer;
    }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[String] 문장 속 단어(indexOf(), substring())]]></title>
            <link>https://velog.io/@0_0ni/String-%EB%AC%B8%EC%9E%A5-%EC%86%8D-%EB%8B%A8%EC%96%B4indexOf-substring</link>
            <guid>https://velog.io/@0_0ni/String-%EB%AC%B8%EC%9E%A5-%EC%86%8D-%EB%8B%A8%EC%96%B4indexOf-substring</guid>
            <pubDate>Thu, 02 Feb 2023 12:17:30 GMT</pubDate>
            <description><![CDATA[<h3 id="문장-속-단어">문장 속 단어</h3>
<p>한 개의 문장이 주어지면 그 문장 속에서 가장 긴 단어를 출력하는 프로그램을 작성하세요.
문장 속의 각 단어는 공백으로 구분됩니다.</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>첫 줄에 길이가 100을 넘지 않는 한 개의 문장이 주어집니다. 문장은 영어 알파벳으로만 구성되어 있습니다.</li>
<li>첫 줄에 가장 긴 단어를 출력합니다. 가장 길이가 긴 단어가 여러 개일 경우, 가장 앞쪽에 위치한 단어를 출력합니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<h4 id="입력">입력</h4>
<p> it is time to study</p>
<h4 id="출력">출력</h4>
<p> study</p>
<hr>
<h3 id="구현">구현</h3>
<pre><code class="language-java"> // (1)
import java.util.Scanner;

public class Main {

    public String solution(String str) {
        String answer = &quot;&quot;;
        int max = Integer.MIN_VALUE;

        String[] s = str.split(&quot; &quot;);
        for (String x : s) {
            int len = x.length();
            if (len &gt; max) {
                max = len;
                answer = x;
            }
        }
        return answer;
    }

    public static void main(String[] args){
      Main T = new Main();
      Scanner kb = new Scanner(System.in);
      String str = kb.next();
      System.out.println(T.solution(&quot;it is time to study&quot;));
    }
}

------------------------------------------------------------

 // (2) IndexOf(), substring() 사용
public class Main {

    public String solution(String str) {
        String answer = &quot;&quot;;
        int max = Integer.MIN_VALUE;
        int pos; 

        while ((pos = str.indexOF(&#39;&#39;)) != -1) {
            String temp = str.substring(0, pos);
            int len = temp.length();
            if (len &gt; max) {
                 max = len;
                 answer = temp;
            }
            str = str.substring(pos+1);
        }

        if(str.length() &gt; max) answer = str;

        return answer;
    }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[String] 대소문자 변환]]></title>
            <link>https://velog.io/@0_0ni/String-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90-%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@0_0ni/String-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90-%EB%B3%80%ED%99%98</guid>
            <pubDate>Thu, 02 Feb 2023 11:26:59 GMT</pubDate>
            <description><![CDATA[<h3 id="대소문자-변환">대소문자 변환</h3>
<p>대문자와 소문자가 같이 존재하는 문자열을 입력 받아,
대문자는 소문자로 소문자는 대문자로 변환하여 출력하는 프로그램 작성</p>
<hr>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>첫 줄에 문자열이 입력된다. 문자열의 길이는 100을 넘지 않는다.</li>
<li>문자열은 영어 알파벳으로만 구성되어 있다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<h4 id="입력">입력</h4>
<p> StuDY</p>
<h4 id="출력">출력</h4>
<p> sTUdy</p>
<hr>
<h3 id="구현">구현</h3>
<pre><code class="language-java">import java.util.Scanner;

public class Main {

    public String solution(String str) {
        String answer = &quot;&quot;;

        // (1)
        for( char x : str.toCharArray() ) {
            if (Character.isLowerCase(x)) answer += Character.toUpperCase(x);
            else answer += Character.toLowerCase(x);
        }

        // (2) 아스키코드 사용
        // 대문자 : 65 ~ 90
        // 소문자 : 97 ~ 122
        // 대소문자의 차이는 97-65 = 32로, 소문자에서 32를 빼면 대문자가 된다.
        for( char x : str.toCharArray() ) {
           if( x&gt;= 97 &amp;&amp; x &lt;= 122) answer += (char)(x-32);
           else answer += (char)(x+32);
        }

        return answer;
    }

    public static void main(String[] args){
      Main T = new Main();
      Scanner kb = new Scanner(System.in);
      String str = kb.next();
      System.out.println(T.solution(&quot;StuDY&quot;));
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[String] 문자 찾기]]></title>
            <link>https://velog.io/@0_0ni/String-%EB%AC%B8%EC%9E%90-%EC%B0%BE%EA%B8%B0</link>
            <guid>https://velog.io/@0_0ni/String-%EB%AC%B8%EC%9E%90-%EC%B0%BE%EA%B8%B0</guid>
            <pubDate>Thu, 02 Feb 2023 11:25:50 GMT</pubDate>
            <description><![CDATA[<h3 id="문자-찾기">문자 찾기</h3>
<p>첫 줄에 문자열이 주어지고, 두 번째 줄에 문자가 주어진다.
문자열은 영어 알파벳으로만 구성되어 있다.</p>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<h4 id="입력">입력</h4>
<p> Computercooler
 c</p>
<h4 id="출력">출력</h4>
<p> 2</p>
<hr>
<h3 id="구현">구현</h3>
<pre><code class="language-java"> import java.util.*;
 class Main {
     public int solution(String str, char t) {
         int answer = 0;
        str = str.toUpperCase();       //대소문자 통일 후 비교
        t = Character.toUpperCase(t); 

        // (1)
        for(int i=0; i &lt; str.length(); i++) {
            if (str.charAt(i) == t) answer++;
        }

        // (2) 향상된 for문
        for(char x : str.toCharArray()) {
            if (x==t) answer++;
        }

        return answer;
    }

     public static void main(String[] args) {
         Main T = new Main();
            Scanner kb = new Scanner(System.in);
            String str = =kb.next();
         char c = kb.next().charAt(0);

         System.out.println(T.solution(str, c));
    }  
 }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스][Java] Lv.1 정수 제곱근 판별]]></title>
            <link>https://velog.io/@0_0ni/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-Lv.1-%EC%A0%95%EC%88%98-%EC%A0%9C%EA%B3%B1%EA%B7%BC-%ED%8C%90%EB%B3%84</link>
            <guid>https://velog.io/@0_0ni/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-Lv.1-%EC%A0%95%EC%88%98-%EC%A0%9C%EA%B3%B1%EA%B7%BC-%ED%8C%90%EB%B3%84</guid>
            <pubDate>Thu, 02 Feb 2023 01:22:49 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명">문제 설명</h3>
<p>임의의 양의 정수 n에 대해, n이 어떤 양의 정수 x의 제곱인지 아닌지 판단하려 합니다.
n이 양의 정수 x의 제곱이라면 x+1의 제곱을 리턴하고, n이 양의 정수 x의 제곱이 아니라면 -1을 리턴하는 함수를 완성하세요.</p>
<hr>
<h3 id="제한-사항">제한 사항</h3>
<ul>
<li>n은 1이상, 50000000000000 이하인 양의 정수입니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<table>
<thead>
<tr>
<th align="left">n</th>
<th align="left">return</th>
</tr>
</thead>
<tbody><tr>
<td align="left">121</td>
<td align="left">144</td>
</tr>
<tr>
<td align="left">3</td>
<td align="left">-1</td>
</tr>
</tbody></table>
<hr>
<h3 id="입출력-예-설명">입출력 예 설명</h3>
<h4 id="입출력-예-1">입출력 예 #1</h4>
<p>121은 양의 정수 11의 제곱이므로, (11+1)를 제곱한 144를 리턴합니다.</p>
<h4 id="입출력-예-2">입출력 예 #2</h4>
<p>3은 양의 정수의 제곱이 아니므로, -1을 리턴합니다.</p>
<hr>
<h3 id="풀이">풀이</h3>
<pre><code class="language-java">class Solution {
   public long solution(long n) {
        long answer = 0;
        Double x = Math.sqrt(n);

        if ( x == x.intValue() ) {
            answer = (long)Math.pow(x+1, 2);
        } else {
            answer = -1;
        }

        return answer;
    }
}</code></pre>
<h3 id="다른-풀이">다른 풀이</h3>
<pre><code class="language-java">// (1)
class Solution {
    public long solution(long n) {
       if (Math.pow((int)Math.sqrt(n), 2) == n) {
               return (long)Math.pow(Math.sqrt(n) + 1,2);
       }

       return -1;
    }
}

// (2)
class Solution {
    public long solution(long n) {

      double i = Math.sqrt(n);

      return Math.floor(i) == i ? (long)Math.pow(i+1, 2) : -1;
    }
}</code></pre>
]]></description>
        </item>
    </channel>
</rss>