<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>앵앵</title>
    <link>https://leejinae.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 14 Apr 2026 16:38:56 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>오늘도알찬하루</managingEditor>
    <item>
      <title>TreeSet, Set에 저장된 객체 검색</title>
      <link>https://leejinae.tistory.com/124</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1746887004822&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;
import java.util.*;

class Node implements Comparable&amp;lt;Node&amp;gt; {
    int y, x;
    Node(int y, int x) {
        this.y = y;
        this.x = x;
    }

    @Override
    public int compareTo(Node o) {

    	
    	// y 오름차순
    	if (this.y &amp;lt; o.y) return -1;
    	if (this.y &amp;gt; o.y) return 1;
    	// x 내림차순
    	if (this.x &amp;gt; o.x) return -1;
    	if (this.x &amp;lt; o.x) return 1;
    	
		return 0;
		
		// 내림차순

		
		
    	
//        if (this.y != o.y) return Integer.compare(this.y, o.y); // y 오름차순
//        return Integer.compare(o.x, this.x); // x 내림차순
    }

    @Override
    public String toString() {
        return &quot;(&quot; + y + &quot;, &quot; + x + &quot;)&quot;;
    }
}

public class TreeSetTest {
    public static void main(String[] args) {
        TreeSet&amp;lt;Node&amp;gt; set = new TreeSet&amp;lt;&amp;gt;();
        
        for (int i = 0; i &amp;lt; 10; i++) {
        	set.add(new Node(i*50, i+10));
        	set.add(new Node(i*50, i+200));
		}
        
        for (int i = 0; i &amp;lt; 10; i++) {
        	set.add(new Node(i*10, i+10));
		}


        // y &amp;gt;= 0 인 Node들만 출력
        Node lowerBound = new Node(0, Integer.MAX_VALUE); // (y=0)이상 찾기
        for (Node node : set.tailSet(lowerBound)) {
            System.out.println(node);
        }
        
        
        Node target = new Node(200, Integer.MAX_VALUE); // (y=200)이상 찾기
        SortedSet&amp;lt;Node&amp;gt; tail = set.tailSet(target);
        
        System.out.println(&quot;===========================================&quot;);
        System.out.println(tail);
        Iterator&amp;lt;Node&amp;gt; it = tail.iterator();
        while (it.hasNext()) {
			
        	
        	Node node = it.next();
        	System.out.println(node.y + &quot; , &quot; + node.x);
		}
        	
        
        
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래밍/java</category>
      <author>오늘도알찬하루</author>
      <guid isPermaLink="true">https://leejinae.tistory.com/124</guid>
      <comments>https://leejinae.tistory.com/124#entry124comment</comments>
      <pubDate>Sat, 10 May 2025 23:24:38 +0900</pubDate>
    </item>
    <item>
      <title>HashMap을 탐색(순회) 방법</title>
      <link>https://leejinae.tistory.com/123</link>
      <description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;HashMap Traversal Methods&lt;/title&gt;
    &lt;style&gt;
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            margin: 20px;
        }
        pre {
            background-color: #f4f4f4;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            overflow-x: auto;
        }
        code {
            color: #d63384;
            font-family: monospace;
        }
        h2 {
            color: #333;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
            border: 2px solid #ddd;
        }
        table, th, td {
            border: 2px solid #ddd;
        }
        th, td {
            padding: 10px;
            text-align: left;
        }
        th {
            background-color: yellow;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h2&gt;1. entrySet() 이용&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;entrySet()&lt;/code&gt;은 &lt;code&gt;HashMap&lt;/code&gt;의 모든 키-값 쌍을 &lt;code&gt;Map.Entry&lt;/code&gt; 객체로 반환합니다.
    &lt;/p&gt;
    &lt;pre&gt;&lt;code&gt;for (Map.Entry&amp;lt;String, Integer&amp;gt; entry : map.entrySet()) {
    System.out.println(&quot;Key: &quot; + entry.getKey() + &quot;, Value: &quot; + entry.getValue());
}&lt;/code&gt;&lt;/pre&gt;
    &lt;h3&gt;특징&lt;/h3&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;구조:&lt;/strong&gt; &lt;code&gt;Map.Entry&lt;/code&gt; 객체를 통해 키와 값을 동시에 접근.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;장점:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;키와 값 모두를 한 번에 접근할 수 있어 효율적.&lt;/li&gt;
                &lt;li&gt;코드가 간결하고 가독성이 높음.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;단점:&lt;/strong&gt; &lt;code&gt;entrySet()&lt;/code&gt;은 &lt;code&gt;Set&amp;lt;Map.Entry&amp;gt;&lt;/code&gt;를 반환하므로 추가적인 객체를 생성.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2&gt;2. keySet() 이용&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;keySet()&lt;/code&gt;은 &lt;code&gt;HashMap&lt;/code&gt;의 모든 키를 &lt;code&gt;Set&lt;/code&gt;으로 반환합니다.
    &lt;/p&gt;
    &lt;pre&gt;&lt;code&gt;for (String key : map.keySet()) {
    System.out.println(&quot;Key: &quot; + key + &quot;, Value: &quot; + map.get(key));
}&lt;/code&gt;&lt;/pre&gt;
    &lt;h3&gt;특징&lt;/h3&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;구조:&lt;/strong&gt; 키를 순회하며 각 키를 이용해 &lt;code&gt;get()&lt;/code&gt;으로 값을 가져옴.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;장점:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;키만 필요할 때 간단하게 사용 가능.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;단점:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;키를 순회하면서 &lt;code&gt;get()&lt;/code&gt; 메서드를 호출하므로, 성능이 상대적으로 떨어질 수 있음(특히 큰 &lt;code&gt;HashMap&lt;/code&gt;에서는 비효율적).&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2&gt;3. values() 이용&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;values()&lt;/code&gt;는 &lt;code&gt;HashMap&lt;/code&gt;의 모든 값을 &lt;code&gt;Collection&lt;/code&gt;으로 반환합니다.
    &lt;/p&gt;
    &lt;pre&gt;&lt;code&gt;for (Integer value : map.values()) {
    System.out.println(&quot;Value: &quot; + value);
}&lt;/code&gt;&lt;/pre&gt;
    &lt;h3&gt;특징&lt;/h3&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;구조:&lt;/strong&gt; 값만 순회하며 접근.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;장점:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;값만 필요할 때 간단히 사용 가능.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;단점:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;값에 대응하는 키를 얻을 수 없음.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2&gt;4. Java 8+ forEach() 이용&lt;/h2&gt;
    &lt;p&gt;
        Java 8부터는 &lt;code&gt;HashMap&lt;/code&gt;에 대해 &lt;code&gt;forEach()&lt;/code&gt; 메서드를 사용할 수 있습니다.
    &lt;/p&gt;
    &lt;pre&gt;&lt;code&gt;map.forEach((key, value) -&gt; {
    System.out.println(&quot;Key: &quot; + key + &quot;, Value: &quot; + value);
});&lt;/code&gt;&lt;/pre&gt;
    &lt;h3&gt;특징&lt;/h3&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;구조:&lt;/strong&gt; 람다 표현식을 통해 키와 값에 동시에 접근.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;장점:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;최신 스타일의 코드로 가독성 높음.&lt;/li&gt;
                &lt;li&gt;병렬 처리를 지원하는 스트림과 쉽게 결합 가능.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;단점:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;Java 8 이상에서만 사용 가능.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2&gt;5. Iterator 이용&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;Iterator&lt;/code&gt;를 사용해 &lt;code&gt;entrySet()&lt;/code&gt;이나 &lt;code&gt;keySet()&lt;/code&gt;을 탐색합니다.
    &lt;/p&gt;
    &lt;pre&gt;&lt;code&gt;Iterator&amp;lt;Map.Entry&amp;lt;String, Integer&amp;gt;&amp;gt; iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry&amp;lt;String, Integer&amp;gt; entry = iterator.next();
    System.out.println(&quot;Key: &quot; + entry.getKey() + &quot;, Value: &quot; + entry.getValue());
}&lt;/code&gt;&lt;/pre&gt;
    &lt;h3&gt;특징&lt;/h3&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;구조:&lt;/strong&gt; &lt;code&gt;Iterator&lt;/code&gt;를 통해 순회하며 요소 제거도 가능.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;장점:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;순회 중 안전하게 요소를 제거할 수 있음.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;단점:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;코드가 다소 장황해짐.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2&gt;차이점 요약&lt;/h2&gt;
    &lt;table&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th&gt;순회 방법&lt;/th&gt;
                &lt;th&gt;키 접근&lt;/th&gt;
                &lt;th&gt;값 접근&lt;/th&gt;
                &lt;th&gt;성능&lt;/th&gt;
                &lt;th&gt;사용 시기&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;code&gt;entrySet()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;가능&lt;/td&gt;
                &lt;td&gt;가능&lt;/td&gt;
                &lt;td&gt;효율적&lt;/td&gt;
                &lt;td&gt;키와 값을 동시에 접근할 때&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;code&gt;keySet()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;가능&lt;/td&gt;
                &lt;td&gt;가능&lt;/td&gt;
                &lt;td&gt;비효율적&lt;/td&gt;
                &lt;td&gt;키만 필요하거나 간단한 순회 시&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;code&gt;values()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;불가능&lt;/td&gt;
                &lt;td&gt;가능&lt;/td&gt;
                &lt;td&gt;효율적&lt;/td&gt;
                &lt;td&gt;값만 필요한 경우&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;code&gt;forEach()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;가능&lt;/td&gt;
                &lt;td&gt;가능&lt;/td&gt;
                &lt;td&gt;효율적&lt;/td&gt;
                &lt;td&gt;람다를 활용하여 코드 간결화 시&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;code&gt;Iterator&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;가능&lt;/td&gt;
                &lt;td&gt;가능&lt;/td&gt;
                &lt;td&gt;보통&lt;/td&gt;
                &lt;td&gt;순회 중 요소를 제거해야 할 때&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;h2&gt;추천&lt;/h2&gt;
    &lt;ul&gt;
        &lt;li&gt;키와 값을 모두 접근해야 한다면 &lt;strong&gt;&lt;code&gt;entrySet()&lt;/code&gt;&lt;/strong&gt;이나 &lt;strong&gt;&lt;code&gt;forEach()&lt;/code&gt;&lt;/strong&gt;가 가장 효율적.&lt;/li&gt;
        &lt;li&gt;키만 필요하면 &lt;code&gt;keySet()&lt;/code&gt;, 값만 필요하면 &lt;code&gt;values()&lt;/code&gt;.&lt;/li&gt;
        &lt;li&gt;요소 제거를 포함한 순회는 &lt;strong&gt;&lt;code&gt;Iterator&lt;/code&gt;&lt;/strong&gt;를 사용.&lt;/li&gt;
    &lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</description>
      <category>프로그래밍/java</category>
      <category>entryset</category>
      <category>foreach</category>
      <category>HashMap</category>
      <category>keyset</category>
      <category>values()</category>
      <author>오늘도알찬하루</author>
      <guid isPermaLink="true">https://leejinae.tistory.com/123</guid>
      <comments>https://leejinae.tistory.com/123#entry123comment</comments>
      <pubDate>Thu, 2 Jan 2025 23:15:40 +0900</pubDate>
    </item>
    <item>
      <title>HashMap 순회 에러 방지</title>
      <link>https://leejinae.tistory.com/122</link>
      <description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;HashMap Iterator Removal&lt;/title&gt;
    &lt;style&gt;
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            margin: 20px;
        }
        pre {
            background-color: #f4f4f4;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            overflow-x: auto;
        }
        code {
            color: #d63384;
            font-family: monospace;
        }
        h2 {
            color: #333;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h2&gt;문제: 일반적인 순회에서 요소 제거&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;HashMap&lt;/code&gt;을 &lt;code&gt;for-each&lt;/code&gt; 루프나 &lt;code&gt;keySet()&lt;/code&gt; 등을 통해 순회하면서 &lt;code&gt;remove()&lt;/code&gt; 메서드를 직접 호출하면, &lt;code&gt;HashMap&lt;/code&gt;의 내부 구조가 변경되므로 &lt;code&gt;ConcurrentModificationException&lt;/code&gt;이 발생합니다.
    &lt;/p&gt;
    &lt;pre&gt;&lt;code&gt;HashMap&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
map.put(&quot;Alice&quot;, 30);
map.put(&quot;Bob&quot;, 25);
map.put(&quot;Charlie&quot;, 35);

// 순회 중 요소를 직접 제거하려고 시도
for (String key : map.keySet()) {
    if (map.get(key) &lt; 30) {
        map.remove(key); // 예외 발생: ConcurrentModificationException
    }
}&lt;/code&gt;&lt;/pre&gt;

    &lt;h2&gt;해결 방법: Iterator를 사용한 안전한 제거&lt;/h2&gt;
    &lt;p&gt;
        &lt;code&gt;Iterator&lt;/code&gt;는 &lt;code&gt;remove()&lt;/code&gt; 메서드를 제공하여 순회 중 안전하게 요소를 제거할 수 있습니다.
    &lt;/p&gt;
    &lt;pre&gt;&lt;code&gt;HashMap&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
map.put(&quot;Alice&quot;, 30);
map.put(&quot;Bob&quot;, 25);
map.put(&quot;Charlie&quot;, 35);

Iterator&amp;lt;Map.Entry&amp;lt;String, Integer&amp;gt;&amp;gt; iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry&amp;lt;String, Integer&amp;gt; entry = iterator.next();
    if (entry.getValue() &lt; 30) { // 값이 30보다 작은 경우 제거
        iterator.remove(); // 안전하게 요소 제거
    }
}

// 결과 출력
System.out.println(map); // {Alice=30, Charlie=35}&lt;/code&gt;&lt;/pre&gt;

    &lt;h2&gt;왜 Iterator를 사용해야 할까?&lt;/h2&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;동기화 문제 방지:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;&lt;code&gt;Iterator&lt;/code&gt;는 내부적으로 &lt;em&gt;fail-fast&lt;/em&gt; 메커니즘을 사용해 동기화 문제를 방지.&lt;/li&gt;
                &lt;li&gt;&lt;code&gt;remove()&lt;/code&gt; 호출 시 &lt;code&gt;HashMap&lt;/code&gt;의 상태를 안전하게 업데이트.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;구조적 변경 감지:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;&lt;code&gt;HashMap&lt;/code&gt;은 구조적 변경(요소 추가/삭제 등)이 발생할 때 즉시 예외를 던져 무결성을 유지.&lt;/li&gt;
                &lt;li&gt;&lt;code&gt;Iterator&lt;/code&gt;는 이러한 변경을 감지하고 안전한 방식으로 처리.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;성능:&lt;/strong&gt;
            &lt;ul&gt;
                &lt;li&gt;&lt;code&gt;Iterator&lt;/code&gt;를 통해 요소를 제거하면 내부 버킷(bucket)과 해싱 구조를 최적화하며 동작.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2&gt;요약&lt;/h2&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;요소(element):&lt;/strong&gt; &lt;code&gt;HashMap&lt;/code&gt;의 각 키-값 쌍.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;순회 중 제거 문제:&lt;/strong&gt; &lt;code&gt;HashMap&lt;/code&gt;의 구조 변경 시 &lt;code&gt;ConcurrentModificationException&lt;/code&gt;이 발생.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;해결책:&lt;/strong&gt; &lt;code&gt;Iterator&lt;/code&gt;의 &lt;code&gt;remove()&lt;/code&gt; 메서드를 사용해 안전하게 요소를 제거.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;
        &lt;strong&gt;결론:&lt;/strong&gt; &lt;code&gt;Iterator&lt;/code&gt;는 구조적 무결성을 유지하면서 순회 중 요소를 안전하게 제거하는 가장 표준적인 방법입니다.
    &lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</description>
      <category>프로그래밍/java</category>
      <category>ConcurrentModificationException</category>
      <category>iterator</category>
      <author>오늘도알찬하루</author>
      <guid isPermaLink="true">https://leejinae.tistory.com/122</guid>
      <comments>https://leejinae.tistory.com/122#entry122comment</comments>
      <pubDate>Thu, 2 Jan 2025 23:05:24 +0900</pubDate>
    </item>
    <item>
      <title>hashset, treeset 비교</title>
      <link>https://leejinae.tistory.com/121</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;/p&gt;
&lt;h1&gt;Java HashSet과 TreeSet 비교 및 사용 예제&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HashSet vs TreeSet 비교&lt;/h2&gt;
&lt;table border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;특징&lt;/th&gt;
&lt;th&gt;HashSet&lt;/th&gt;
&lt;th&gt;TreeSet&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;데이터 구조&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;해시 테이블 기반&lt;/td&gt;
&lt;td&gt;이진 탐색 트리 기반 (Red-Black Tree)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;highlight&quot;&gt;&lt;b&gt;정렬 여부&lt;/b&gt;&lt;/td&gt;
&lt;td class=&quot;highlight&quot;&gt;&lt;b&gt;순서를 보장하지 않음&lt;/b&gt;&lt;/td&gt;
&lt;td class=&quot;highlight&quot;&gt;&lt;b&gt;자동 정렬 (기본: 오름차순)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;highlight&quot;&gt;&lt;b&gt;중복 허용 여부&lt;/b&gt;&lt;/td&gt;
&lt;td class=&quot;highlight&quot;&gt;&lt;b&gt;중복 값 허용하지 않음&lt;/b&gt;&lt;/td&gt;
&lt;td class=&quot;highlight&quot;&gt;&lt;b&gt;중복 값 허용하지 않음&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;삽입/삭제/검색: O(1) (평균)&lt;/td&gt;
&lt;td&gt;삽입/삭제/검색: O(log n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;null 허용 여부&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;1개의 null 값 허용&lt;/td&gt;
&lt;td&gt;null 값을 허용하지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;사용 사례&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;빠른 검색 및 순서가 중요하지 않은 경우&lt;/td&gt;
&lt;td&gt;정렬된 데이터나 범위 검색이 필요한 경우&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HashSet 사용 예제&lt;/h2&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;
import java.util.HashSet;

public class HashSetExample {
    public static void main(String[] args) {
        HashSet set = new HashSet&amp;lt;&amp;gt;();

        // 요소 추가
        set.add(&quot;Apple&quot;);
        set.add(&quot;Banana&quot;);
        set.add(&quot;Orange&quot;);
        set.add(&quot;Apple&quot;); // 중복은 추가되지 않음

        // 출력
        System.out.println(&quot;HashSet: &quot; + set);

        // 요소 검색
        System.out.println(&quot;Contains 'Apple': &quot; + set.contains(&quot;Apple&quot;));

        // 요소 제거
        set.remove(&quot;Banana&quot;);
        System.out.println(&quot;After removing 'Banana': &quot; + set);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;출력:&lt;/h4&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;
HashSet: [Orange, Apple, Banana]
Contains 'Apple': true
After removing 'Banana': [Orange, Apple]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;TreeSet 사용 예제&lt;/h2&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;
import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet set = new TreeSet&amp;lt;&amp;gt;();

        // 요소 추가
        set.add(&quot;Apple&quot;);
        set.add(&quot;Banana&quot;);
        set.add(&quot;Orange&quot;);
        set.add(&quot;Apple&quot;); // 중복은 추가되지 않음

        // 출력
        System.out.println(&quot;TreeSet: &quot; + set);

        // 첫 번째와 마지막 요소 확인
        System.out.println(&quot;First: &quot; + set.first());
        System.out.println(&quot;Last: &quot; + set.last());

        // 요소 제거
        set.remove(&quot;Banana&quot;);
        System.out.println(&quot;After removing 'Banana': &quot; + set);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;출력:&lt;/h4&gt;
&lt;pre class=&quot;mathematica&quot;&gt;&lt;code&gt;
TreeSet: [Apple, Banana, Orange]
First: Apple
Last: Orange
After removing 'Banana': [Apple, Orange]
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래밍/java</category>
      <category>HashSet</category>
      <category>TreeSet</category>
      <author>오늘도알찬하루</author>
      <guid isPermaLink="true">https://leejinae.tistory.com/121</guid>
      <comments>https://leejinae.tistory.com/121#entry121comment</comments>
      <pubDate>Sun, 22 Dec 2024 16:07:18 +0900</pubDate>
    </item>
    <item>
      <title>hashmap vs treemap 비교</title>
      <link>https://leejinae.tistory.com/120</link>
      <description>---
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;HashMap vs TreeMap&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;HashMap과 TreeMap의 비교&lt;/h1&gt;
    &lt;h2&gt;주요 비교&lt;/h2&gt;
    &lt;table border=&quot;1&quot;&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th&gt;특징&lt;/th&gt;
                &lt;th&gt;HashMap&lt;/th&gt;
                &lt;th&gt;TreeMap&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr&gt;
                &lt;td&gt;데이터 구조&lt;/td&gt;
                &lt;td&gt;해시 테이블(Hash Table) 기반으로 키-값을 저장합니다.&lt;/td&gt;
                &lt;td&gt;이진 탐색 트리(Red-Black Tree) 기반으로 키-값을 저장합니다.&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;정렬 여부&lt;/td&gt;
                &lt;td&gt;키 순서를 보장하지 않습니다.&lt;/td&gt;
                &lt;td&gt;키를 자동으로 &lt;strong&gt;정렬(기본 오름차순)&lt;/strong&gt;합니다. (사용자 정의 Comparator 가능)&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;시간 복잡도&lt;/td&gt;
                &lt;td&gt;삽입/검색/삭제: 평균적으로 &lt;strong&gt;O(1)&lt;/strong&gt;&lt;br&gt;최악의 경우(충돌): &lt;strong&gt;O(n)&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;삽입/검색/삭제: &lt;strong&gt;O(log n)&lt;/strong&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;null 허용 여부&lt;/td&gt;
                &lt;td&gt;키: 1개의 &lt;code&gt;null&lt;/code&gt; 허용&lt;br&gt;값: 다수의 &lt;code&gt;null&lt;/code&gt; 허용&lt;/td&gt;
                &lt;td&gt;키: &lt;code&gt;null&lt;/code&gt; 허용하지 않음&lt;br&gt;값: 다수의 &lt;code&gt;null&lt;/code&gt; 허용&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;성능&lt;/td&gt;
                &lt;td&gt;일반적으로 빠름 (해시 기반 접근).&lt;/td&gt;
                &lt;td&gt;느림 (트리 기반 접근).&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;적합한 사용 사례&lt;/td&gt;
                &lt;td&gt;빠른 검색/삽입/삭제가 중요한 경우.&lt;/td&gt;
                &lt;td&gt;데이터가 정렬된 상태로 필요하거나 범위 검색이 필요한 경우.&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;
&lt;br&gt;
  
    &lt;h2&gt;예제 코드&lt;/h2&gt;
    &lt;h3&gt;HashMap 사용 예제&lt;/h3&gt;
    &lt;pre&gt;
    &lt;br&gt;
    &lt;br&gt;
&lt;code&gt;
import java.util.HashMap;

public class HashMapExample {
    public static void main(String[] args) {
        HashMap&lt;Integer, String&gt; hashMap = new HashMap&lt;&gt;();
        hashMap.put(1, &quot;One&quot;);
        hashMap.put(2, &quot;Two&quot;);
        hashMap.put(3, &quot;Three&quot;);

        System.out.println(&quot;HashMap: &quot; + hashMap);
        System.out.println(&quot;Value for key 2: &quot; + hashMap.get(2));

        hashMap.remove(2);
        System.out.println(&quot;After removal: &quot; + hashMap);

        System.out.println(&quot;Keys: &quot; + hashMap.keySet());
        System.out.println(&quot;Values: &quot; + hashMap.values());
    }
}
&lt;/code&gt;
   &lt;/pre&gt;
&lt;br&gt;

    &lt;h4&gt;출력:&lt;/h4&gt;
    &lt;pre&gt;
&lt;code&gt;
HashMap: {1=One, 2=Two, 3=Three}
Value for key 2: Two
After removal: {1=One, 3=Three}
Keys: [1, 3]
Values: [One, Three]
&lt;/code&gt;
    &lt;/pre&gt;
&lt;br&gt;
    &lt;h3&gt;TreeMap 사용 예제&lt;/h3&gt;
    &lt;pre&gt;
&lt;code&gt;
import java.util.TreeMap;

public class TreeMapExample {
    public static void main(String[] args) {
        TreeMap&lt;Integer, String&gt; treeMap = new TreeMap&lt;&gt;();
        treeMap.put(3, &quot;Three&quot;);
        treeMap.put(1, &quot;One&quot;);
        treeMap.put(2, &quot;Two&quot;);

        System.out.println(&quot;TreeMap: &quot; + treeMap);
        System.out.println(&quot;First Key: &quot; + treeMap.firstKey());
        System.out.println(&quot;Last Key: &quot; + treeMap.lastKey());

        System.out.println(&quot;SubMap (1 to 3): &quot; + treeMap.subMap(1, 3));
    }
}
&lt;/code&gt;
	&lt;/pre&gt;
    &lt;br&gt;
    &lt;h4&gt;출력:&lt;/h4&gt;
    &lt;pre&gt;
&lt;code&gt;
TreeMap: {1=One, 2=Two, 3=Three}
First Key: 1
Last Key: 3
SubMap (1 to 3): {1=One, 2=Two}
&lt;/code&gt;
    &lt;/pre&gt;    
&lt;/body&gt;
&lt;/html&gt;</description>
      <category>프로그래밍/java</category>
      <category>HashMap</category>
      <category>submap</category>
      <category>TreeMap</category>
      <author>오늘도알찬하루</author>
      <guid isPermaLink="true">https://leejinae.tistory.com/120</guid>
      <comments>https://leejinae.tistory.com/120#entry120comment</comments>
      <pubDate>Sat, 21 Dec 2024 03:09:53 +0900</pubDate>
    </item>
    <item>
      <title>[grafana]Invalid type for column time, must be of type timestamp or unix timestamp, got</title>
      <link>https://leejinae.tistory.com/119</link>
      <description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;PostgreSQL Query Discussion&lt;/title&gt;
    &lt;style&gt;
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            margin: 20px;
        }
        .user, .assistant {
            margin-bottom: 20px;
        }
        .user {
            color: blue;
        }
        .assistant {
            color: green;
        }
        .code {
            background-color: #f4f4f4;
            border: 1px solid #ddd;
            padding: 10px;
            margin: 10px 0;
            white-space: pre-wrap;
            font-family: monospace;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;user&quot;&gt;
        &lt;div class=&quot;code&quot;&gt;
            &lt;code&gt;
               SELECT &lt;br&gt;
                datname AS &quot;metric&quot;,&lt;br&gt;
                count(datname) AS &quot;Value&quot;,&lt;br&gt;
                date_trunc('minute', xact_start) AS time&lt;br&gt;
                FROM&lt;br&gt;
                pg_stat_activity&lt;br&gt;
                GROUP BY&lt;br&gt;
                datname,&lt;br&gt;
                xact_start&lt;br&gt;
                ORDER BY&lt;br&gt;
                xact_start&lt;br&gt;
            &lt;/code&gt;
        &lt;/div&gt;
        쿼리는 Invalid type for column time, must be of type timestamp or unix timestamp, got: &lt;nil&gt; &lt;nil&gt; 에러
    &lt;/p&gt;
&lt;/div&gt;

&lt;div class=&quot;assistant&quot;&gt;
    &lt;p&gt;&lt;strong&gt;Assistant:&lt;/strong&gt; 죄송합니다. &lt;code&gt;pg_stat_activity&lt;/code&gt; 테이블에서 트랜잭션이 시작되지 않은 세션의 &lt;code&gt;xact_start&lt;/code&gt; 값은 &lt;code&gt;NULL&lt;/code&gt;일 수 있습니다. 이를 방지하기 위해 &lt;code&gt;xact_start&lt;/code&gt;가 &lt;code&gt;NULL&lt;/code&gt;이 아닌 경우에만 집계하도록 필터링을 추가해야 합니다. 또한, Grafana에서 요구하는 형식에 맞게 &lt;code&gt;time&lt;/code&gt; 열을 적절히 처리해야 합니다.&lt;/p&gt;
    &lt;p&gt;다음은 &lt;code&gt;xact_start&lt;/code&gt;가 &lt;code&gt;NULL&lt;/code&gt;이 아닌 경우에만 데이터를 집계하여 Grafana에서 사용할 수 있는 쿼리입니다:&lt;/p&gt;
    &lt;div class=&quot;code&quot;&gt;
        &lt;code&gt;
            SELECT&lt;br&gt;
            &amp;nbsp;&amp;nbsp;date_trunc('minute', xact_start) AS time,&lt;br&gt;
            &amp;nbsp;&amp;nbsp;datname AS metric,&lt;br&gt;
            &amp;nbsp;&amp;nbsp;count(*) AS value&lt;br&gt;
            FROM&lt;br&gt;
            &amp;nbsp;&amp;nbsp;pg_stat_activity&lt;br&gt;
            WHERE&lt;br&gt;
            &amp;nbsp;&amp;nbsp;xact_start IS NOT NULL&lt;br&gt;
            GROUP BY&lt;br&gt;
            &amp;nbsp;&amp;nbsp;time, datname&lt;br&gt;
            ORDER BY&lt;br&gt;
            &amp;nbsp;&amp;nbsp;time&lt;br&gt;
        &lt;/code&gt;
    &lt;/div&gt;
    &lt;p&gt;이 쿼리는 다음과 같은 기능을 합니다:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;code&gt;date_trunc('minute', xact_start)&lt;/code&gt;를 사용하여 &lt;code&gt;xact_start&lt;/code&gt;를 분 단위로 잘라냅니다.&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;xact_start&lt;/code&gt;가 &lt;code&gt;NULL&lt;/code&gt;이 아닌 경우에만 데이터를 필터링합니다.&lt;/li&gt;
        &lt;li&gt;각 데이터베이스(&lt;code&gt;datname&lt;/code&gt;)별로 트랜잭션의 수(&lt;code&gt;count(*)&lt;/code&gt;)를 집계합니다.&lt;/li&gt;
        &lt;li&gt;결과를 시간(&lt;code&gt;time&lt;/code&gt;)을 기준으로 정렬합니다.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;이렇게 하면 Grafana가 요구하는 시계열 데이터 형식에 맞게 데이터를 준비할 수 있습니다. 이 쿼리를 Grafana에 입력하면 시계열 패널에 각 데이터베이스의 트랜잭션 수를 시간별로 시각화할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>클라우드/monitoring</category>
      <category>grafana</category>
      <category>postgres</category>
      <category>timestamp</category>
      <author>오늘도알찬하루</author>
      <guid isPermaLink="true">https://leejinae.tistory.com/119</guid>
      <comments>https://leejinae.tistory.com/119#entry119comment</comments>
      <pubDate>Mon, 15 Jul 2024 22:15:57 +0900</pubDate>
    </item>
    <item>
      <title>[grafana] Value column must have numeric datatype, column: Database type: string value: postgres</title>
      <link>https://leejinae.tistory.com/118</link>
      <description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;PostgreSQL Query Discussion&lt;/title&gt;
    &lt;style&gt;
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            margin: 20px;
        }
        .user, .assistant {
            margin-bottom: 20px;
        }
        .user {
            color: blue;
        }
        .assistant {
            color: green;
        }
        .code {
            background-color: #f4f4f4;
            border: 1px solid #ddd;
            padding: 10px;
            margin: 10px 0;
            white-space: pre-wrap;
            font-family: monospace;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;assistant&quot;&gt;
    &lt;p&gt;&lt;strong&gt;Assistant:&lt;/strong&gt; Grafana 패널에 시계열 데이터를 시각화하려면 해당 시계열 데이터를 쿼리하여 Grafana가 이해할 수 있는 형식으로 가져와야 합니다. PostgreSQL의 &lt;code&gt;pg_stat_activity&lt;/code&gt; 테이블에서 데이터베이스 이름(&lt;code&gt;datname&lt;/code&gt;)과 트랜잭션 시작 시간(&lt;code&gt;xact_start&lt;/code&gt;)을 사용하여 시계열 데이터를 추출하는 쿼리를 작성할 수 있습니다.&lt;/p&gt;
    &lt;p&gt;다음은 Grafana 패널을 만드는 데 사용할 수 있는 쿼리 예제입니다:&lt;/p&gt;
    &lt;div class=&quot;code&quot;&gt;
        &lt;code&gt;
            SELECT&lt;br&gt;
            &amp;nbsp;&amp;nbsp;datname AS &quot;Database&quot;,&lt;br&gt;
            &amp;nbsp;&amp;nbsp;count(datname) AS &quot;Session Count&quot;,&lt;br&gt;
            &amp;nbsp;&amp;nbsp;xact_start AS &quot;Transaction Start Time&quot;&lt;br&gt;
            FROM&lt;br&gt;
            &amp;nbsp;&amp;nbsp;pg_stat_activity&lt;br&gt;
            GROUP BY&lt;br&gt;
            &amp;nbsp;&amp;nbsp;datname,&lt;br&gt;
            &amp;nbsp;&amp;nbsp;xact_start&lt;br&gt;
            ORDER BY&lt;br&gt;
            &amp;nbsp;&amp;nbsp;xact_start&lt;br&gt;
        &lt;/code&gt;
    &lt;/div&gt;
    &lt;p&gt;이 쿼리는 각 데이터베이스 별 세션 수와 각 트랜잭션의 시작 시간을 반환합니다. Grafana에서 이 쿼리를 사용하여 시계열 데이터를 시각화할 수 있습니다. 데이터베이스 별로 세션 수의 변화와 각 트랜잭션의 시작 시간을 시계열 차트에 표시할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;

&lt;div class=&quot;user&quot;&gt;
    &lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt; Value column must have numeric datatype, column: Database type: string value: postgres 이런 에러가 발생하네&lt;/p&gt;
&lt;/div&gt;

&lt;div class=&quot;assistant&quot;&gt;
    &lt;p&gt;&lt;strong&gt;Assistant:&lt;/strong&gt; 죄송합니다. Grafana의 시계열 패널에서 사용하는 쿼리는 시간(timestamp), 메트릭(metric), 값(value)의 세 가지 필드가 필요합니다. &lt;code&gt;datname&lt;/code&gt; 필드는 문자열 타입이므로 메트릭으로 사용할 수 없습니다. 대신, 각 데이터베이스의 트랜잭션 수를 시간별로 집계하여 표시해야 합니다.&lt;/p&gt;
    &lt;p&gt;이를 위해서는 &lt;code&gt;xact_start&lt;/code&gt;의 시간 부분을 기준으로 세션 수를 집계해야 합니다. 다음은 이러한 쿼리를 작성하는 방법입니다:&lt;/p&gt;
    &lt;div class=&quot;code&quot;&gt;
        &lt;code&gt;
            SELECT&lt;br&gt;
            &amp;nbsp;&amp;nbsp;date_trunc('minute', xact_start) AS time,&lt;br&gt;
            &amp;nbsp;&amp;nbsp;datname AS metric,&lt;br&gt;
            &amp;nbsp;&amp;nbsp;count(*) AS value&lt;br&gt;
            FROM&lt;br&gt;
            &amp;nbsp;&amp;nbsp;pg_stat_activity&lt;br&gt;
            WHERE&lt;br&gt;
            &amp;nbsp;&amp;nbsp;xact_start IS NOT NULL&lt;br&gt;
            GROUP BY&lt;br&gt;
            &amp;nbsp;&amp;nbsp;time, datname&lt;br&gt;
            ORDER BY&lt;br&gt;
            &amp;nbsp;&amp;nbsp;time&lt;br&gt;
        &lt;/code&gt;
    &lt;/div&gt;
    &lt;p&gt;이 쿼리는 &lt;code&gt;xact_start&lt;/code&gt;를 분 단위로 잘라서(time) 각 데이터베이스(datname) 별로 트랜잭션 수(count(*))를 집계합니다. 이렇게 하면 Grafana에서 시계열 차트로 시각화할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>클라우드/monitoring</category>
      <category>grafana</category>
      <category>postgres</category>
      <category>value column must have numeric datatype</category>
      <author>오늘도알찬하루</author>
      <guid isPermaLink="true">https://leejinae.tistory.com/118</guid>
      <comments>https://leejinae.tistory.com/118#entry118comment</comments>
      <pubDate>Mon, 15 Jul 2024 22:09:03 +0900</pubDate>
    </item>
    <item>
      <title>grafana를 사용한 postgresql  transaction모니터링</title>
      <link>https://leejinae.tistory.com/117</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;user&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;User:&lt;/b&gt; postgresql이 pg_stat_activity 테이블에서 xact_start, querystart차이&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;assistant&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Assistant:&lt;/b&gt; pg_stat_activity 테이블은 현재 실행 중인 PostgreSQL 세션에 대한 정보를 제공합니다. 여기에는 각 세션의 시작 시간, 실행 중인 쿼리의 시작 시간 및 트랜잭션 시작 시간과 같은 정보가 포함됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;code&gt;xact_start&lt;/code&gt;: 현재 세션이 시작된 시간으로, 해당 세션이 트랜잭션을 시작한 시간을 나타냅니다. 이는 현재 세션이 트랜잭션 내에서 작동 중인지 여부를 파악하는 데 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;code&gt;query_start&lt;/code&gt;: 현재 세션에서 현재 실행 중인 쿼리의 시작 시간입니다. 이것은 현재 세션에서 실행 중인 쿼리의 시작 시간을 나타내며, 다음 쿼리가 실행되기 전까지 해당 값이 갱신되지 않습니다. 이것은 현재 세션이 얼마나 오랫동안 쿼리를 실행하고 있는지를 추적하는 데 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 두 값의 차이는 세션이 트랜잭션을 시작한 후 현재까지 얼마나 오랫동안 실행되고 있는지를 나타냅니다. 만약 이 값이 크다면, 해당 세션이 오랜 시간동안 활동 중이거나 긴 트랜잭션을 가지고 있을 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;user&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;User:&lt;/b&gt; pg_stat_activity를 count(datname), xact_start는 Time series 로 grafana 패널 만드는 쿼리&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;assistant&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Assistant:&lt;/b&gt; Grafana 패널에 시계열 데이터를 시각화하려면 해당 시계열 데이터를 쿼리하여 Grafana가 이해할 수 있는 형식으로 가져와야 합니다. PostgreSQL의 &lt;code&gt;pg_stat_activity&lt;/code&gt; 테이블에서 데이터베이스 이름(&lt;code&gt;datname&lt;/code&gt;)과 트랜잭션 시작 시간(&lt;code&gt;xact_start&lt;/code&gt;)을 사용하여 시계열 데이터를 추출하는 쿼리를 작성할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT
  datname AS &quot;Database&quot;,
  count(datname) AS &quot;Session Count&quot;,
  xact_start AS &quot;Transaction Start Time&quot;
FROM
  pg_stat_activity
GROUP BY
  datname,
  xact_start
ORDER BY
  xact_start
        &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 쿼리는 각 데이터베이스 별 세션 수와 각 트랜잭션의 시작 시간을 반환합니다. Grafana에서 이 쿼리를 사용하여 시계열 데이터를 시각화할 수 있습니다. 데이터베이스 별로 세션 수의 변화와 각 트랜잭션의 시작 시간을 시계열 차트에 표시할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;user&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;User:&lt;/b&gt; Value column must have numeric datatype, column: Database type: string value: postgres 이런 에러가 발생하네&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;assistant&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Assistant:&lt;/b&gt; Grafana의 시계열 패널에서 사용하는 쿼리는 시간(timestamp), 메트릭(metric), 값(value)의 세 가지 필드가 필요합니다. &lt;code&gt;datname&lt;/code&gt; 필드는 문자열 타입이므로 메트릭으로 사용할 수 없습니다. 대신, 각 데이터베이스의 트랜잭션 수를 시간별로 집계하여 표시해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해서는 &lt;code&gt;xact_start&lt;/code&gt;의 시간 부분을 기준으로 세션 수를 집계해야 합니다. 다음은 이러한 쿼리를 작성하는 방법입니다:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT
  date_trunc('minute', xact_start) AS time,
  datname AS metric,
  count(*) AS value
FROM
  pg_stat_activity
WHERE
  xact_start IS NOT NULL
GROUP BY
  time, datname
ORDER BY
  time
        &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 쿼리는 &lt;code&gt;xact_start&lt;/code&gt;를 분 단위로 잘라서(&lt;code&gt;time&lt;/code&gt;) 각 데이터베이스(&lt;code&gt;datname&lt;/code&gt;) 별로 트랜잭션 수(&lt;code&gt;count(*)&lt;/code&gt;)를 집계합니다. 이렇게 하면 Grafana에서 시계열 차트로 시각화할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;user&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;User:&lt;/b&gt; SELECT datname AS &quot;metric&quot;, count(datname) AS &quot;Value&quot;, date_trunc('minute', xact_start) AS time FROM pg_stat_activity GROUP BY datname, xact_start ORDER BY xact_start 쿼리는 Invalid type for column time, must be of type timestamp or unix timestamp, got: 에러가 나오네&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;assistant&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Assistant:&lt;/b&gt; &lt;code&gt;pg_stat_activity&lt;/code&gt; 테이블에서 트랜잭션이 시작되지 않은 세션의 &lt;code&gt;xact_start&lt;/code&gt; 값은 &lt;code&gt;NULL&lt;/code&gt;일 수 있습니다. 이를 방지하기 위해 &lt;code&gt;xact_start&lt;/code&gt;가 &lt;code&gt;NULL&lt;/code&gt;이 아닌 경우에만 집계하도록 필터링을 추가해야 합니다. 또한, Grafana에서 요구하는 형식에 맞게 &lt;code&gt;time&lt;/code&gt; 열을 적절히 처리해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 &lt;code&gt;xact_start&lt;/code&gt;가 &lt;code&gt;NULL&lt;/code&gt;이 아닌 경우에만 데이터를 집계하여 Grafana에서 사용할 수 있는 쿼리입니다:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT
  date_trunc('minute', xact_start) AS time,
  datname AS metric,
  count(*) AS value
FROM
  pg_stat_activity
WHERE
  xact_start IS NOT NULL
GROUP BY
  time, datname
ORDER BY
  time
        &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 쿼리는 다음과 같은 기능을 합니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;date_trunc('minute', xact_start)&lt;/code&gt;를 사용하여 &lt;code&gt;xact_start&lt;/code&gt;를 분 단위로 잘라냅니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;User:&lt;/b&gt; Value column must have numeric datatype, column: Database type: string value: postgres 이런 에러가 발생하네&lt;/li&gt;
&lt;li&gt;각 데이터베이스(&lt;code&gt;datname&lt;/code&gt;)별로 트랜잭션의 수(&lt;code&gt;count(*)&lt;/code&gt;)를 집계합니다.&lt;/li&gt;
&lt;li&gt;결과를 시간(&lt;code&gt;time&lt;/code&gt;)을 기준으로 정렬합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 Grafana가 요구하는 시계열 데이터 형식에 맞게 데이터를 준비할 수 있습니다. 이 쿼리를 Grafana에 입력하면 시계열 패널에 각 데이터베이스의 트랜잭션 수를 시간별로 시각화할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>클라우드/monitoring</category>
      <category>grafana</category>
      <category>pg_stat_activity</category>
      <category>xart모니터링</category>
      <author>오늘도알찬하루</author>
      <guid isPermaLink="true">https://leejinae.tistory.com/117</guid>
      <comments>https://leejinae.tistory.com/117#entry117comment</comments>
      <pubDate>Wed, 15 May 2024 16:47:37 +0900</pubDate>
    </item>
    <item>
      <title>Spring 프레임워크와 Tomcat의 차이</title>
      <link>https://leejinae.tistory.com/116</link>
      <description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;Spring 프레임워크와 Tomcat의 차이&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;h1&gt;Spring 프레임워크와 Tomcat의 차이&lt;/h1&gt;

&lt;h2&gt;스프링 프레임워크(Spring Framework)&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;스프링은 Java 기반의 웹 애플리케이션 및 엔터프라이즈 애플리케이션을 개발하기 위한 오픈 소스 프레임워크입니다.&lt;/li&gt;
  &lt;li&gt;주요 기능은 의존성 주입(Dependency Injection), 관점 지향 프로그래밍(Aspect-Oriented Programming), 포터블 리미팩토링(POJO), 템플릿을 통한 데이터 접근(Data Access Templates), 트랜잭션 관리(Transaction Management) 등이 있습니다.&lt;/li&gt;
  &lt;li&gt;스프링은 애플리케이션의 모듈화, 테스트 용이성, 코드의 재사용성 등을 촉진합니다.&lt;/li&gt;
  &lt;li&gt;주로 개발자들이 소프트웨어 아키텍처를 유연하게 만들기 위해 사용됩니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Tomcat&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;아파치 톰캣(Apache Tomcat)은 Java Servlet, JavaServer Pages(JSP) 등을 실행하기 위한 웹 애플리케이션 서버입니다.&lt;/li&gt;
  &lt;li&gt;Tomcat은 웹 애플리케이션의 배포, 실행, 관리를 담당합니다.&lt;/li&gt;
  &lt;li&gt;Servlet 컨테이너로서 동작하며, HTTP 요청에 대한 처리 및 응답을 처리합니다.&lt;/li&gt;
  &lt;li&gt;Tomcat은 스프링이나 다른 프레임워크를 이용하여 개발된 Java 웹 애플리케이션을 호스팅하고 실행하는 고 실행하는 데 사용됩니다.  &lt;li&gt;</description>
      <category>IT-기타</category>
      <author>오늘도알찬하루</author>
      <guid isPermaLink="true">https://leejinae.tistory.com/116</guid>
      <comments>https://leejinae.tistory.com/116#entry116comment</comments>
      <pubDate>Wed, 15 May 2024 08:54:21 +0900</pubDate>
    </item>
    <item>
      <title>소문자-&amp;gt;대문자 변환</title>
      <link>https://leejinae.tistory.com/115</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1703855961462&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*; 
import java.util.*; 

public class Main {
//	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//	static StringTokenizer st;
	
	
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static StringTokenizer st;
		
	public static void main(String[] args)throws Exception{

		st = new StringTokenizer(br.readLine());
		
		char a=st.nextToken().charAt(0);
//		int b=Integer.parseInt(st.nextToken());

// 아스키코드표를 보면, 대소문자는 정확히 32만큼 차이가 나므로,
//  char a를 (int)로 형변환 후 32를 빼주면, 소문자-&amp;gt;대문자가 됨
		int b = (int)a-32;
		
		
		System.out.println((char)b);

	}

}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래밍/문제풀이</category>
      <category>소문자 대문자 변환 코드</category>
      <author>오늘도알찬하루</author>
      <guid isPermaLink="true">https://leejinae.tistory.com/115</guid>
      <comments>https://leejinae.tistory.com/115#entry115comment</comments>
      <pubDate>Fri, 29 Dec 2023 22:20:24 +0900</pubDate>
    </item>
  </channel>
</rss>