<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Juan Sedano</title>
    <description>The latest articles on DEV Community by Juan Sedano (@jsedano).</description>
    <link>https://dev.to/jsedano</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F243570%2F41d19551-7a33-499c-89fb-570825727bbe.jpeg</url>
      <title>DEV Community: Juan Sedano</title>
      <link>https://dev.to/jsedano</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jsedano"/>
    <language>en</language>
    <item>
      <title>Simple web QR maker with zxing and Thymeleaf</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Mon, 17 Jun 2024 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/simple-web-qr-maker-with-zxing-and-thymeleaf-28fb</link>
      <guid>https://dev.to/jsedano/simple-web-qr-maker-with-zxing-and-thymeleaf-28fb</guid>
      <description>&lt;p&gt;Encode text into QR Code with &lt;a href="https://github.com/zxing/zxing"&gt;zxing&lt;/a&gt; and display it using thymeleaf. Live demo &lt;a href="https://demo.jsedano.dev/simpleqr/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can find the complete code for this &lt;a href="https://github.com/jsedano/simple-qr"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the method to encode a String into an image, and then encode the image into a base 64 String that represents the png, based around the code in this &lt;a href="https://www.digitalocean.com/community/tutorials/java-qr-code-generator-zxing-example"&gt;tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jsedano/simple-qr/blob/main/src/main/java/dev/jsedano/simpleqr/service/QRCreator.java"&gt;QRCreator.java&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  private String unsafeCreateQRImage(String qrCodeText, int size)
      throws WriterException, IOException {
    // Create the ByteMatrix for the QR-Code that encodes the given String
    Hashtable&amp;lt;EncodeHintType, ErrorCorrectionLevel&amp;gt; hintMap = new Hashtable&amp;lt;&amp;gt;();
    hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
    BitMatrix byteMatrix =
        qrCodeWriter.encode(qrCodeText, BarcodeFormat.QR_CODE, size, size, hintMap);
    // Make the BufferedImage that are to hold the QRCode
    int matrixWidth = byteMatrix.getWidth();
    BufferedImage image = new BufferedImage(matrixWidth, matrixWidth, BufferedImage.TYPE_INT_RGB);
    image.createGraphics();

    Graphics2D graphics = (Graphics2D) image.getGraphics();
    graphics.setColor(Color.WHITE);
    graphics.fillRect(0, 0, matrixWidth, matrixWidth);
    // Paint and save the image using the ByteMatrix
    graphics.setColor(Color.BLACK);

    for (int i = 0; i &amp;lt; matrixWidth; i++) {
      for (int j = 0; j &amp;lt; matrixWidth; j++) {
        if (byteMatrix.get(i, j)) {
          graphics.fillRect(i, j, 1, 1);
        }
      }
    }
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ImageIO.write(image, "png", bos);
    byte[] imageBytes = bos.toByteArray();

    Base64.Encoder encoder = Base64.getEncoder();
    return encoder.encodeToString(imageBytes);
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this on the &lt;code&gt;controller&lt;/code&gt; for the thymeleaf templates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jsedano/simple-qr/blob/main/src/main/java/dev/jsedano/simpleqr/controller/SimpleQRController.java"&gt;SimpleQRController.java&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  @RequestMapping("/")
  public String newRandomSelect(Model model) {
    model.addAttribute("textAndQRImage", new TextAndQRImage());
    return "inputQR";
  }

  @RequestMapping("/show")
  public String showQR(Model model, TextAndQRImage textAndQRImage, HttpSession session) {
    if (Objects.isNull(textAndQRImage.getText()) || textAndQRImage.getText().isEmpty()) {
      return "redirect:/simpleqr/";
    }
    String qrImage = qrCreator.createQRImage(textAndQRImage.getText(), 800);
    if (Objects.isNull(qrImage) || qrImage.isEmpty()) {
      return "redirect:/simpleqr/";
    }
    textAndQRImage.setText(textAndQRImage.getText());
    textAndQRImage.setBase64Image(qrCreator.createQRImage(textAndQRImage.getText(), 800));

    model.addAttribute("textAndQRImage", textAndQRImage);
    return "showQR";
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Part of &lt;a href="https://github.com/jsedano/simple-qr/blob/main/src/main/resources/templates/inputQR.html"&gt;inputQR.html&lt;/a&gt; that asks for the text that will be encoded into a QR code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;form action="/simpleqr/show" th:object="${textAndQRImage}" method="POST"&amp;gt;

        &amp;lt;input type="text" placeholder="input text here" th:field="*{text}"&amp;gt;

        &amp;lt;button type="submit"&amp;gt;Generate QR&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then we display the QR code in &lt;a href="https://github.com/jsedano/simple-qr/blob/main/src/main/resources/templates/showQR.html"&gt;showQR.html&lt;/a&gt; template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body&amp;gt;

    &amp;lt;div&amp;gt;
        &amp;lt;img class="img-responsive" th:src="@{'data:image/png;base64,'+${textAndQRImage.base64Image}}"/&amp;gt;
    &amp;lt;/div&amp;gt;

&amp;lt;h2 th:text=${textAndQRImage.text}&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;/body&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download the complete code for this here: &lt;a href="https://github.com/jsedano/simple-qr"&gt;simple-qr code&lt;/a&gt;. Live demo on: &lt;a href="https://demo.jsedano.dev/simpleqr/"&gt;simple-qr live&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
      <category>thymeleaf</category>
      <category>qr</category>
    </item>
    <item>
      <title>Plain Thymeleaf</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Mon, 17 Apr 2023 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/plain-thymeleaf-53jg</link>
      <guid>https://dev.to/jsedano/plain-thymeleaf-53jg</guid>
      <description>&lt;p&gt;&lt;code&gt;Thymeleaf&lt;/code&gt; is an HTML (&lt;a href="https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#what-kind-of-templates-can-thymeleaf-process"&gt;and more&lt;/a&gt;) template engine for Java. This is the core in action with nothing else.&lt;/p&gt;

&lt;p&gt;You can find the complete code for this here: &lt;a href="https://github.com/jsedano/examples/tree/main/only-thymeleaf"&gt;only-thymeleaf&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All of this is just putting into a project what has being posted in this &lt;a href="https://stackoverflow.com/a/71995574/1845671"&gt;stackoverflow answer&lt;/a&gt; which in turn was found on this &lt;a href="https://github.com/thymeleaf/thymeleaf/issues/561#issuecomment-490648829"&gt;comment on github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We begin by getting only the core jar for Thymeleaf (the latest one at the time this post was written).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jsedano/examples/blob/main/only-thymeleaf/pom.xml"&gt;pom.xml&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.thymeleaf&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;thymeleaf&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;3.1.1.RELEASE&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we create our &lt;code&gt;template&lt;/code&gt; inside resources on a directory apptly named &lt;code&gt;templates&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jsedano/examples/blob/main/only-thymeleaf/src/main/resources/templates/index.html"&gt;src/main/resources/templates/index.html&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en" xmlns:th="http://www.thymeleaf.org"&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="UTF-8"&amp;gt;
  &amp;lt;title&amp;gt;Thymeleaf hello world&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;p&amp;gt;First name: &amp;lt;span th:text="${first_name}?: '(no first name specified)'"/&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Last name: &amp;lt;span th:text="${last_name}?: '(no last name specified)'"/&amp;gt;.&amp;lt;/p&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the &lt;code&gt;span tag&lt;/code&gt; we have &lt;code&gt;th&lt;/code&gt; which is how all data attributes starts on Thymeleaf, you can see that it’s declared as a namespace definition above on the html tag. We are also using a variable expression &lt;code&gt;${}&lt;/code&gt; with an Elvis operator &lt;code&gt;?:&lt;/code&gt; which is an special operator that only returns it’s value when the evaluated expression returns null, which means if &lt;code&gt;first_name&lt;/code&gt; is null then &lt;code&gt;(no first name specified)&lt;/code&gt; will be returned.&lt;/p&gt;

&lt;p&gt;Now to bring it all together:&lt;a href="https://github.com/jsedano/examples/blob/main/only-thymeleaf/src/main/java/dev/jsedano/examples/onlythymeleaf/Main.java"&gt;src/main/java/dev/jsedano/examples/onlythymeleaf/Main.java&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var resolver = new ClassLoaderTemplateResolver();
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setCharacterEncoding("UTF-8");
resolver.setPrefix("/templates/");
resolver.setSuffix(".html");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we are not using Spring or nothing to helps us with dependency injection we will create objects the traditional way, setting up the prefix for where the templates will be stored and the suffix for them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var context = new Context();
if (args.length != 0) {
  context.setVariable("first_name", args[0]);
  if (args.length &amp;gt; 1) {
    context.setVariable("last_name", args[1]);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will be the context which will hold the objects that Thymeleaf will use to generate the html.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(resolver);

var result = templateEngine.process("index", context);
System.out.println(result);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we create a &lt;code&gt;TemplateEngine&lt;/code&gt; object and pass the &lt;code&gt;resolver&lt;/code&gt;, then we call &lt;code&gt;process&lt;/code&gt; on the &lt;code&gt;templateEngine&lt;/code&gt; object with the name of the template and the context we created above.&lt;/p&gt;

&lt;p&gt;We can create our fat jar running &lt;code&gt;mvn verify&lt;/code&gt; and then call it with &lt;code&gt;java -jar ./target/only-thymeleaf-1.0-jar-with-dependencies.jar&lt;/code&gt; to print the result of the template processing, if we send variables when we executed we can see how they get replace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;only-thymeleaf % java -jar ./target/only-thyme leaf-1.0-jar-with-dependencies.jar
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="UTF-8"&amp;gt;
  &amp;lt;title&amp;gt;Thymeleaf hello world&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;p&amp;gt;First name: &amp;lt;span&amp;gt;(no first name specified)&amp;lt;/span&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Last name: &amp;lt;span&amp;gt;(no last name specified)&amp;lt;/span&amp;gt;.&amp;lt;/p&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

only-thymeleaf % java -jar ./target/only-thymeleaf-1.0-jar-with-dependencies.jar juan sedano
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="UTF-8"&amp;gt;
  &amp;lt;title&amp;gt;Thymeleaf hello world&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;p&amp;gt;First name: &amp;lt;span&amp;gt;juan&amp;lt;/span&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Last name: &amp;lt;span&amp;gt;sedano&amp;lt;/span&amp;gt;.&amp;lt;/p&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more information on Thymeleaf you can go directly to the &lt;a href="https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html"&gt;thymeleaf docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Download the complete code for this here: &lt;a href="https://github.com/jsedano/examples/tree/main/only-thymeleaf"&gt;only-thymeleaf&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
      <category>thymeleaf</category>
    </item>
    <item>
      <title>Lissajous curve Java</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Fri, 28 Oct 2022 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/lissajous-curve-java-4pe6</link>
      <guid>https://dev.to/jsedano/lissajous-curve-java-4pe6</guid>
      <description>&lt;p&gt;Just a Lissajous curve on Java displayed on a JFrame.&lt;/p&gt;

&lt;p&gt;You can find the complete code for this here: &lt;a href="https://github.com/jsedano/examples/blob/main/java-snippets/Lissajous.java"&gt;Lissajous.java&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First of all, the code is a complete rip-off from &lt;a href="https://www.gopl.io"&gt;The Go Programming Language&lt;/a&gt; book, specifically from this &lt;a href="https://github.com/adonovan/gopl.io/blob/master/ch1/lissajous/main.go"&gt;code from chapter 1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I won’t even pretend to understand the maths on this one, so lets just dive into the code, first we initialize our window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int size = 100;
JFrame frame = new JFrame("Lissajous");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(2*size+1, 2*size+1));
frame.add(panel);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that we have a non resizable JFrame on the middle of the screen, that terminates the program when closed which contains a JPanel where we can draw, in order to do so we only need the Graphics from the JPanel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Graphics g = panel.getGraphics();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we start shamelessly translating the Go code from the link above to Java:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;double cycles = 5;
double angularResolution = 0.001;
long delay = 80;
int frames = 64;
for(;;){
    double frequency = Math.random() * 3.0;
    float phase = 0.0f;
    for( int i = 0; i &amp;lt; frames; i++) {
        g.setColor(Color.BLACK);
        g.fillRect(0,0, panel.getWidth(), panel.getHeight());
        g.setColor(Color.GREEN);
        for(double t = 0.0; t &amp;lt; cycles*2*Math.PI; t+= angularResolution){
            double x = Math.sin(t);
            double y = Math.sin(t * frequency + phase);
            g.drawRect( (size + (int)(x*size+0.5)), (size + (int)(y*size+0.5)),1,1);
        }
        phase += 0.1;
        Thread.sleep(delay);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since its a single file, if we have Java 11 or above we can run it without compiling with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java Lissajous.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we should see this:&lt;/p&gt;

&lt;p&gt;&lt;a href="///assets/images/lissajous-curve-java/lissajous-curve-java.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JB2UPGdW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://jsedano.dev/assets/images/lissajous-curve-java/lissajous-curve-java.gif" alt="lissajous-curve-java" width="848" height="848"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Download the complete code for this here: &lt;a href="https://github.com/jsedano/examples/blob/main/java-snippets/Lissajous.java"&gt;Lissajous.java&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Java Redis pub/sub example with Jedis</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Mon, 19 Sep 2022 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/java-redis-pubsub-example-with-jedis-196j</link>
      <guid>https://dev.to/jsedano/java-redis-pubsub-example-with-jedis-196j</guid>
      <description>&lt;p&gt;This is a Redis pub/sub example written in Java using Jedis.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can find the complete code for this here: &lt;a href="https://github.com/jsedano/examples/tree/main/redis-pub-sub"&gt;Java Redis pub/sub example&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For more neat stuff that Redis can do look here: &lt;a href="https://dev.to/jsedano/redis-2022-4dhd"&gt;Redis 2022&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jsedano/examples/tree/main/redis-pub-sub"&gt;Download the code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Have an instance of &lt;a href="https://redis.io/docs/stack/get-started/install/docker/"&gt;redis-stack&lt;/a&gt; running.&lt;/li&gt;
&lt;li&gt;Apache Maven 3.8.6&lt;/li&gt;
&lt;li&gt;Java 17&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Libraries used
&lt;/h3&gt;

&lt;p&gt;We are only using &lt;a href="https://github.com/redis/jedis"&gt;jedis&lt;/a&gt; in order to keep the example simple.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redis Commands used
&lt;/h3&gt;

&lt;h4&gt;
  
  
  subscribe
&lt;/h4&gt;

&lt;p&gt;this is used in order to subscribe to one or more channels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;subscribe channel1 channel2... channelN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  unsubscribe
&lt;/h4&gt;

&lt;p&gt;unsubscribe current client to one or more channels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unsubscribe channel1 channel2... channelN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  psubscribe
&lt;/h4&gt;

&lt;p&gt;instead of subscribing to a channel, this allows you to subscribe to one of more patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psubscribe pattern1 pattern2... patternN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for example if you subscribe to &lt;code&gt;foo*&lt;/code&gt; it means that you will get the messages meant for all the channels that start with &lt;code&gt;foo&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  punsubscribe
&lt;/h4&gt;

&lt;p&gt;unsubscribe from one or more patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;punsubscribe pattern1 pattern2... patternN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  publish
&lt;/h4&gt;

&lt;p&gt;publish sends a message to connected clients, returns the number of clients that got the message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;publish aChannel 'some message'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ping
&lt;/h4&gt;

&lt;p&gt;sends a ping from a client to the server, optionally you can send a message and the ping will echo it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ping a message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code walkthrough
&lt;/h3&gt;

&lt;p&gt;We need to extend &lt;code&gt;JedisPubSub&lt;/code&gt; in order to give our client functionality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import redis.clients.jedis.JedisPubSub;

public class LogPubSub extends JedisPubSub {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To keep this example simple we are only going to add very basic functionality, in order to know which client is the one that got the message we are adding a name field.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  private String name;

  public LogPubSub(String name) {
    this.name = name;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;subscribe&lt;/code&gt;, &lt;code&gt;unsubscribe&lt;/code&gt;, &lt;code&gt;psubscribe&lt;/code&gt;, &lt;code&gt;punsubscribe&lt;/code&gt; and &lt;code&gt;pong&lt;/code&gt; (which is the one that a successful ping triggers) we only print the information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  public void onSubscribe(String channel, int subscribedChannels) {
    System.out.printf(
        "name: %s method: %s channel: %s subscribedChannels: %d\n",
        name, "onSubscribe", channel, subscribedChannels);
  }

  public void onUnsubscribe(String channel, int subscribedChannels) {
    System.out.printf(
        "name: %s method: %s channel: %s subscribedChannels: %d\n",
        name, "onUnsubscribe", channel, subscribedChannels);
  }

  public void onPUnsubscribe(String pattern, int subscribedChannels) {
    System.out.printf(
        "name: %s method: %s patten: %s subscribedChannels: %d\n",
        name, "onPUnsubscribe", pattern, subscribedChannels);
  }

  public void onPSubscribe(String pattern, int subscribedChannels) {
    System.out.printf(
        "name: %s method: %s patten: %s subscribedChannels: %d\n",
        name, "onPSubscribe", pattern, subscribedChannels);
  }

  public void onPong(String message) {
    System.out.printf("name: %s method: %s message: %s\n", name, "onPong", message);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When receiving a message in the client apart from printing the information if the message is a ping then we will do a &lt;code&gt;ping&lt;/code&gt;. If receiving the String “exit” we will unsubscribe from that channel or pattern (in the case of client subscribed using psubscribe).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  public void onMessage(String channel, String message) {
    System.out.printf(
        "name: %s method: %s channel: %s message: %s\n", name, "onMessage", channel, message);
    switch (message) {
      case "ping":
        this.ping();
        break;
      case "exit":
        this.unsubscribe(channel);
        break;
      default:
        if (message.indexOf("ping") == 0 &amp;amp;&amp;amp; message.indexOf(" ") == 4) {
          this.ping(message.substring(5));
        }
    }
  }

  public void onPMessage(String pattern, String channel, String message) {
    System.out.printf(
        "name: %s method: %s pattern: %s channel: %s message: %s\n",
        name, "onPMessage", pattern, channel, message);
    switch (message) {
      case "ping":
        this.ping();
        break;
      case "exit":
        this.punsubscribe(pattern);
        break;
      default:
        if (message.indexOf("ping") == 0 &amp;amp;&amp;amp; message.indexOf(" ") == 4) {
          this.ping(message.substring(5));
        }
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we only need to make a &lt;code&gt;JedisPooled&lt;/code&gt; connection and used it to subscribe to a channel or pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JedisPooled jedis = new JedisPooled("localhost", 6379);
ExecutorService executor = Executors.newFixedThreadPool(4);

executor.execute(() -&amp;gt; jedis.subscribe(new LogPubSub("onlyOne"), "dev.one"));
executor.execute(() -&amp;gt; jedis.subscribe(new LogPubSub("oneAndTwo"), "dev.one", "dev.two"));
executor.execute(() -&amp;gt; jedis.psubscribe(new LogPubSub("pattern"), "dev.*"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to run the subscribe and psubscribe on a thread since those are blocking operations.&lt;/p&gt;

&lt;p&gt;In this example we are creating three clients, which we will identify as “onlyOne”, “oneAndTwo” and “pattern”, this doesn’t mean anything to redis, but it will be easier for us to keep track of whats happening.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“onlyOne” is subscribed to channel “dev.one”.&lt;/li&gt;
&lt;li&gt;“oneAndTwo” is subscribed to channels “dev.one” and “dev.two”.&lt;/li&gt;
&lt;li&gt;“pattern” is subscribed to the pattern “dev.*”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this we could send messages using publish on our &lt;a href="https://redis.io/docs/stack/insight/"&gt;RedisInsight CLI&lt;/a&gt; which should be running on &lt;a href="http://localhost:8001/redis-stack/browser"&gt;http://localhost:8001/redis-stack/browser&lt;/a&gt; if we installed the &lt;a href="https://redis.io/docs/stack/get-started/install/docker/"&gt;redis-stack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But we will also send messages using jedis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String message = "";
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
  do {
    message = br.readLine();
    int firstSpace = message.indexOf(' ');
    if (firstSpace &amp;gt; 1) {
      jedis.publish(message.substring(0, firstSpace), message.substring(firstSpace + 1));
    }
  } while (!"close".equals(message));
  jedis.close();
  System.exit(0);
} catch (IOException e) {
  throw new RuntimeException(e);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For building the code run &lt;code&gt;mvn package&lt;/code&gt; and a far jar will be generated on target and then you can run it like so &lt;code&gt;java -jar RedisPubSub-1.0.jar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... target % java -jar RedisPubSub-1.0.jar
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
name: pattern method: onPSubscribe patten: dev.* subscribedChannels: 1
name: oneAndTwo method: onSubscribe channel: dev.one subscribedChannels: 1
name: oneAndTwo method: onSubscribe channel: dev.two subscribedChannels: 2
dev.one hello
name: pattern method: onPMessage pattern: dev.* channel: dev.one message: hello
name: oneAndTwo method: onMessage channel: dev.one message: hello
dev.five hello to you
name: pattern method: onPMessage pattern: dev.* channel: dev.five message: hello to you
dev.two also to you
name: pattern method: onPMessage pattern: dev.* channel: dev.two message: also to you
name: oneAndTwo method: onMessage channel: dev.two message: also to you
dev.six exit
name: pattern method: onPMessage pattern: dev.* channel: dev.six message: exit
name: pattern method: onPUnsubscribe patten: dev.* subscribedChannels: 0
dev.two exit
name: oneAndTwo method: onMessage channel: dev.two message: exit
name: oneAndTwo method: onUnsubscribe channel: dev.two subscribedChannels: 1
dev.one ping say my name
name: oneAndTwo method: onMessage channel: dev.one message: ping say my name
name: oneAndTwo method: onPong message: say my name
dev.two are you alive?
dev.five no one is listening here
dev.one this one is alive
name: oneAndTwo method: onMessage channel: dev.one message: this one is alive
dev.one exit
name: oneAndTwo method: onMessage channel: dev.one message: exit
name: oneAndTwo method: onUnsubscribe channel: dev.one subscribedChannels: 0
dev.one not anymore
close
... target %
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download the complete code for this here: &lt;a href="https://github.com/jsedano/examples/tree/main/redis-pub-sub"&gt;Java Redis pub/sub example&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
      <category>redis</category>
    </item>
    <item>
      <title>Redis 2022</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Sat, 17 Sep 2022 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/redis-2022-4dhd</link>
      <guid>https://dev.to/jsedano/redis-2022-4dhd</guid>
      <description>&lt;p&gt;What is Redis (Remote Dictionary Server) on 2022. What can we do with it. How to scale. How to run it on the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Redis?
&lt;/h2&gt;

&lt;p&gt;Redis is a key value store, just like a hash table. It can be used in-memory as cache and data will not be persisted or it can persist the data and be use as data storage. &lt;a href="https://redis.io/docs/data-types/tutorial/#keys"&gt;Keys&lt;/a&gt; can have a length to up to 512 MB.&lt;/p&gt;

&lt;p&gt;It can also be used as a &lt;a href="https://redis.com/solutions/use-cases/messaging/"&gt;message queue / message broker.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Supported data types
&lt;/h2&gt;

&lt;p&gt;Redis supports several data types&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Max Size&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://redis.io/docs/data-types/tutorial/#strings"&gt;Strings&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;512 MB&lt;/td&gt;
&lt;td&gt;Bytes, text, serialized objects, binary arrays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://redis.io/docs/data-types/lists/"&gt;Lists&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2^32 - 1 (4,294,967,295) elements.&lt;/td&gt;
&lt;td&gt;Linked list of Redis Strings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://redis.io/docs/data-types/sets/"&gt;Sets&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2^32 - 1 (4,294,967,295) members.&lt;/td&gt;
&lt;td&gt;Unordered unique Redis Strings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://redis.io/docs/data-types/sorted-sets/"&gt;Sorted Sets&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Not specified&lt;/td&gt;
&lt;td&gt;Every String has also an integer weight that you must set up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://redis.io/docs/data-types/hashes/"&gt;Hashes&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;4,294,967,295 (2^32 - 1) field-value pairs&lt;/td&gt;
&lt;td&gt;Hash table&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://redis.io/docs/data-types/streams/"&gt;Streams&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Not specified&lt;/td&gt;
&lt;td&gt;Used to track real time events and allows consumers and consumer groups to read them&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Special use cases types
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://redis.io/docs/data-types/geospatial/"&gt;Geospatial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Allows to store coordinates and perform operations such as finding the closest one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://redis.io/docs/data-types/geospatial/"&gt;HyperLogLog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not gonna even try to summarize this one, &lt;a href="http://antirez.com/news/75"&gt;read this instead.&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://redis.io/docs/data-types/geospatial/"&gt;Bitmaps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use a String like a bit vector, allows performing bitwise operations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://redis.io/docs/data-types/geospatial/"&gt;Bitfields&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Allows storing, atomic read, write and read operations for 1 bit unsigned integers to 63 signed bit integers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional support
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://redis.io/docs/stack/json/"&gt;RedisJSON&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Adds facilities to store json documents and adds operations to be able to access / update fields using &lt;a href="https://goessner.net/articles/JsonPath/"&gt;JSONPath&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://redis.io/docs/stack/graph/"&gt;RedisGraph&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A graph database.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://redis.io/docs/stack/timeseries/"&gt;RedisTimeSeries&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Module that adds a time series data structure to Redis, allowing querying by start / end time.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://redis.io/docs/stack/bloom/"&gt;RedisBloom&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Probabilistic data structures.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://redis.io/docs/stack/insight/"&gt;RedisInsight&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Visual support that helps optimizing your stuff on Redis.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://redis.io/docs/manual/pubsub/"&gt;Message queues with Redis Pub/Sub&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We can use Redis to create channels, send messages to the channels and have subscribers that recive the message.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redis on the cloud
&lt;/h2&gt;

&lt;h3&gt;
  
  
  redis cloud
&lt;/h3&gt;

&lt;p&gt;We can use a hosted service using the offer from Redis on &lt;a href="https://redis.com/try-free/"&gt;Redis Cloud&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Or you can install it following &lt;a href="https://developer.redis.com/create/from-source/"&gt;guides detailed here.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://aws.amazon.com/redis/"&gt;aws&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;AWS only supports Redis as an in memmory database, but you could try to install it on a service like EC2 and put a separate storage to persist.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://cloud.google.com/memorystore/docs/redis/redis-overview"&gt;gcp&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Google cloud platform currently does not suppert persisting the data out of the box.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://azure.microsoft.com/en-us/products/cache/"&gt;azure&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Apparently you can persist using out of the box redis services on azure, but they dont recomend it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scalabity
&lt;/h2&gt;

&lt;p&gt;You can scale horizontally using &lt;a href="https://redis.io/docs/manual/scaling/"&gt;Redis Cluster&lt;/a&gt; where you have a master that replicates the information between replicas, but it doesn’t guarantees that you are not going to lose data, if you are unlucky that a replica is randomly selected as master and then it goes down before propagating the changes, it can lose data, unless you configure it so that the master has to acknowledge having replicated the information, but then you have to accept a hit on your performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://redis.io/docs/manual/security/"&gt;Security&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Redis recomends that redis is only used on trusted environments where only trusted clients can access it.&lt;/p&gt;

</description>
      <category>redis</category>
    </item>
    <item>
      <title>Removies</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Mon, 29 Aug 2022 06:43:00 +0000</pubDate>
      <link>https://dev.to/jsedano/removies-599a</link>
      <guid>https://dev.to/jsedano/removies-599a</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;This is an API made with Spring Web, uses &lt;a href="https://springdoc.org"&gt;springdoc-openapi-ui&lt;/a&gt; to expose a swagger-ui on &lt;a href="http://localhost:8080/swagger-ui/index.html"&gt;http://localhost:8080/swagger-ui/index.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using datasets from &lt;a href="https://www.kaggle.com"&gt;kaggle&lt;/a&gt; we load up Redis with movies and TV show information and then it provides endpoints to query the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/redis/jedis"&gt;jedis&lt;/a&gt; is used to interact with Redis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Wacky Wildcards&lt;/p&gt;

&lt;h3&gt;
  
  
  Language Used
&lt;/h3&gt;

&lt;p&gt;Java/Spring&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jsedano"&gt;
        jsedano
      &lt;/a&gt; / &lt;a href="https://github.com/jsedano/removies"&gt;
        removies
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Removies&lt;/h1&gt;
&lt;p&gt;Removies is an api that lets you search movies and tv shows information from a database of movies from several streaming services.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/4958726/187133254-d462f8c6-06f8-457a-b475-98108ee4ba85.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j2BALzRH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/4958726/187133254-d462f8c6-06f8-457a-b475-98108ee4ba85.png" alt="Screen Shot 2022-08-29 at 1 02 21"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
How it works&lt;/h2&gt;
&lt;h3&gt;
How the data is stored:&lt;/h3&gt;
&lt;p&gt;The data is stored as JSON documents using &lt;a href="https://redis.io/docs/stack/json/" rel="nofollow"&gt;RedisJSON&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-java notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;public&lt;/span&gt; &lt;span class="pl-smi"&gt;void&lt;/span&gt; &lt;span class="pl-s1"&gt;insert&lt;/span&gt;(&lt;span class="pl-smi"&gt;String&lt;/span&gt; &lt;span class="pl-s1"&gt;key&lt;/span&gt;, &lt;span class="pl-smi"&gt;MediaDTO&lt;/span&gt; &lt;span class="pl-s1"&gt;mediaDTO&lt;/span&gt;) {
  &lt;span class="pl-s1"&gt;jedisPooled&lt;/span&gt;.&lt;span class="pl-en"&gt;jsonSet&lt;/span&gt;(&lt;span class="pl-s1"&gt;key&lt;/span&gt;, &lt;span class="pl-s1"&gt;gson&lt;/span&gt;.&lt;span class="pl-en"&gt;toJson&lt;/span&gt;(&lt;span class="pl-s1"&gt;mediaDTO&lt;/span&gt;))
}&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;MediaDTO&lt;/code&gt; is the object to be inserted but first it needs to be represented as JSON so we use &lt;code&gt;gson&lt;/code&gt; for that.&lt;/p&gt;
&lt;h3&gt;
How the data is accessed:&lt;/h3&gt;
&lt;p&gt;To access data several &lt;a href="https://redis.io/commands/ft.create/" rel="nofollow"&gt;indexes need to be created&lt;/a&gt;
Then &lt;a href="https://redis.io/docs/stack/search/" rel="nofollow"&gt;RediSearch&lt;/a&gt; is used to make queries.&lt;/p&gt;
&lt;div class="highlight highlight-source-java notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;jedisPooled&lt;/span&gt;.&lt;span class="pl-en"&gt;ftSearch&lt;/span&gt;(
    &lt;span class="pl-s"&gt;"titleIdx"&lt;/span&gt;, &lt;span class="pl-k"&gt;new&lt;/span&gt; &lt;span class="pl-smi"&gt;Query&lt;/span&gt;(&lt;span class="pl-s"&gt;"@title:("&lt;/span&gt; + &lt;span class="pl-s1"&gt;cleanTitle&lt;/span&gt; + &lt;span class="pl-s"&gt;")"&lt;/span&gt;).&lt;span class="pl-en"&gt;returnFields&lt;/span&gt;(&lt;span class="pl-s"&gt;"title"&lt;/span&gt;));
}&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
How to run it locally?&lt;/h2&gt;
&lt;h3&gt;
Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Have an instance of redis-stack running.&lt;/li&gt;
&lt;li&gt;Apache Maven 3.8.6&lt;/li&gt;
&lt;li&gt;Java 17&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
Local installation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Download the following…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/jsedano/removies"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;For reading the datasets &lt;a href="http://opencsv.sourceforge.net"&gt;opencsv&lt;/a&gt; is used. &lt;br&gt;
More libraries used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/google/gson"&gt;gson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://projectlombok.org"&gt;lombok&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Datasets used: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.kaggle.com/datasets/shivamb/disney-movies-and-tv-shows"&gt;Disney+ Movies and TV Shows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kaggle.com/datasets/shivamb/netflix-shows"&gt;Netflix Movies and TV Shows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kaggle.com/datasets/shivamb/amazon-prime-movies-and-tv-shows"&gt;Amazon Prime Movies and TV Shows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kaggle.com/datasets/shivamb/hulu-movies-and-tv-shows"&gt;Hulu Movies and TV Shows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the code and how to run it on &lt;a href="https://github.com/jsedano/removies"&gt;https://github.com/jsedano/removies&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Check out &lt;a href="https://redis.io/docs/stack/get-started/clients/#high-level-client-libraries"&gt;Redis OM&lt;/a&gt;, client libraries for working with Redis as a multi-model database.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Use &lt;a href="https://redis.info/redisinsight"&gt;RedisInsight&lt;/a&gt; to visualize your data in Redis.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Sign up for a &lt;a href="https://redis.info/try-free-dev-to"&gt;free Redis database&lt;/a&gt;.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>redishackathon</category>
    </item>
    <item>
      <title>A custom annotation to apply currying in Java</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Sun, 26 Jun 2022 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/a-custom-annotation-to-apply-currying-in-java-1l68</link>
      <guid>https://dev.to/jsedano/a-custom-annotation-to-apply-currying-in-java-1l68</guid>
      <description>&lt;p&gt;I created a custom annotation in order to apply currying to a method or constructor.&lt;/p&gt;

&lt;p&gt;You can find the complete code for this here: &lt;a href="https://github.com/jsedano/curry"&gt;curry&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more information on currying check this &lt;a href="https://dev.to/jsedano/currying-in-java-2hm"&gt;post&lt;/a&gt; and for a background on annotations in Java check this &lt;a href="https://dev.to/jsedano/java-annotations-khj"&gt;one&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First we create the annotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
public @interface Curry {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We only need the annotation to be processed and then discarded (we don’t need to have it available at run time or recorded on the .class) so we use &lt;code&gt;@Retention(RetentionPolicy.SOURCE)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This annotation will only be used on methods and constructors so we set those as the Target on &lt;code&gt;@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we create a processor for the annotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@SupportedAnnotationTypes("dev.jsedano.curry.annotation.Curry")
@SupportedSourceVersion(SourceVersion.RELEASE_17)
@AutoService(Processor.class)
public class CurryProcessor extends AbstractProcessor {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;@SupportedAnnotationTypes("dev.jsedano.curry.annotation.Curry")&lt;/code&gt; we say that this processor will only look for that particular annotation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@SupportedSourceVersion(SourceVersion.RELEASE_17)&lt;/code&gt; here we are saying the Java version supported.&lt;/p&gt;

&lt;p&gt;The last one is pretty interesting, &lt;code&gt;@AutoService(Processor.class)&lt;/code&gt; is from a Google library called &lt;a href="https://github.com/google/auto/tree/master/service"&gt;auto-service&lt;/a&gt;. In order for the Java compiler to use a processor the class needs to be declared inside the jar on the &lt;code&gt;META-INF/services&lt;/code&gt;directory on the &lt;code&gt;javax.annotation.processing.Processor&lt;/code&gt; file, the auto-service library does that for you.&lt;/p&gt;

&lt;p&gt;Then we need to implement the &lt;code&gt;process&lt;/code&gt; method on out custom processor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public boolean process(Set&amp;lt;? extends TypeElement&amp;gt; annotations, RoundEnvironment roundEnv) {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside our class we get the &lt;code&gt;processingEnv&lt;/code&gt; object that provides us with functionality such as &lt;code&gt;getMessager()&lt;/code&gt; that we use to print a warning message on compile time when the @Curry annotation is used on a method with 1 or more than 10 parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;otherMethods.stream()
    .forEach(
        e -&amp;gt;
            processingEnv
                .getMessager()
                .printMessage(
                    Diagnostic.Kind.MANDATORY_WARNING,
                    "incorrect number of parameters, allowed only between 2 and 1O, will not generate code for this one",
                    e));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also have this one &lt;code&gt;getFiler()&lt;/code&gt; which allows us to create Java source files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(builderClassName);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the &lt;a href="https://github.com/jsedano/curry/tree/main/tests"&gt;tests&lt;/a&gt; module of the project we declare some methods with the @Curry annotation, for example this constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Curry
public AnnotatedClass(
    boolean aBoolean, List&amp;lt;String&amp;gt; aStringList, int aNumber, char aChar, float aFloat) {
  this.aBoolean = aBoolean;
  this.aStringList = aStringList;
  this.aNumber = aNumber;
  this.aChar = aChar;
  this.aFloat = aFloat;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running &lt;code&gt;mvn clean verify&lt;/code&gt; on the parent module we can see the autogenerated code under &lt;code&gt;target/generated-sources/annotations/dev.jsedano.curry.tests&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static java.util.function.Function&amp;lt;java.lang.Boolean,java.util.function.Function&amp;lt;java.util.List&amp;lt;java.lang.String&amp;gt;,java.util.function.Function&amp;lt;java.lang.Integer,java.util.function.Function&amp;lt;java.lang.Character,java.util.function.Function&amp;lt;java.lang.Float,dev.jsedano.curry.tests.AnnotatedClass&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; pentaConstructor(dev.jsedano.curry.util.function.PentaFunction&amp;lt;java.lang.Boolean,java.util.List&amp;lt;java.lang.String&amp;gt;,java.lang.Integer,java.lang.Character,java.lang.Float,dev.jsedano.curry.tests.AnnotatedClass&amp;gt; function) {
    return v0-&amp;gt;v1-&amp;gt;v2-&amp;gt;v3-&amp;gt;v4-&amp;gt; function.apply(v0,v1,v2,v3,v4);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is not pretty looking, but we can use it to then curry the five parameter constructor of the example class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var pentaConstructor = AnnotatedClassCurryer.pentaConstructor(AnnotatedClass::new);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see another example &lt;a href="https://github.com/jsedano/examples/blob/main/curry-examples/src/main/java/dev/jsedano/curry/examples/WgetVersion2.java"&gt;here&lt;/a&gt;, but if you want to compile it you need to do &lt;code&gt;mvn clean install&lt;/code&gt; on the curryer module of &lt;a href="https://github.com/jsedano/curry"&gt;curry&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Curry
public static String wget(
    int connectionTimeout,
    int readTimeout,
    boolean followRedirects,
    String requestMethod,
    String address) {
  try {
    URL url = new URL(address);
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    con.setRequestMethod(requestMethod);
    con.setConnectTimeout(connectionTimeout);
    con.setReadTimeout(readTimeout);
    con.setInstanceFollowRedirects(followRedirects);
    BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer content = new StringBuffer();
    while ((inputLine = in.readLine()) != null) {
      content.append(inputLine);
    }
    in.close();
    return address + " " + content.toString();
  } catch (Exception e) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    e.printStackTrace(pw);
    String stackTrace = sw.toString();
    return address + " " + stackTrace.substring(0, stackTrace.indexOf("\n"));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can set the values we need in a curried way and use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static void main(String[] args) {
  var get =
      WgetVersion2Curryer.wget(WgetVersion2::wget)
          .apply(100)
          .apply(100)
          .apply(false)
          .apply("GET");

  List.of(
          "https://www.google.com",
          "https://www.wikipedia.org",
          "asdf",
          "https://docs.oracle.com/javase/10/docs/api/java/net/package-summary.html",
          "https://jsedano.dev",
          "https://raw.githubusercontent.com/center-key/clabe-validator/main/clabe.ts")
      .parallelStream()
      .map(get)
      .forEach(System.out::println);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download the complete code from this post here: &lt;a href="https://github.com/jsedano/curry"&gt;curry&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Java @Annotations</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Sat, 18 Jun 2022 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/java-annotations-khj</link>
      <guid>https://dev.to/jsedano/java-annotations-khj</guid>
      <description>&lt;p&gt;If you have been using Java for about a week (probably even less) chances are you have already seen some annotations. Let’s review some stuff about them.&lt;/p&gt;

&lt;p&gt;As explained on &lt;a href="%5Bhttps://docs.oracle.com/javase/tutorial/java/annotations/%5D"&gt;https://docs.oracle.com/javase/tutorial/java/annotations/&lt;/a&gt; we can use annotations to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Give information to the compiler&lt;/strong&gt; : so we can detect errors or even suppress warnings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compile-time and deployment-time processing&lt;/strong&gt; : we can generate code, xml files and so on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime processing&lt;/strong&gt; : some annotations can be reviewed at runtime (using reflection).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Annotations can be used anywhere you use a type.&lt;/p&gt;

&lt;p&gt;One interesting fact is that annotations can potentially generate code, but they &lt;strong&gt;can not modify it&lt;/strong&gt;. If you use tools like &lt;a href="%5Bhttps://projectlombok.org%5D"&gt;lombok&lt;/a&gt; you know that they actually modify the code, but they usually achieve this by accessing internal libraries.&lt;/p&gt;

&lt;p&gt;Annotations are defined with the &lt;strong&gt;@interface&lt;/strong&gt; keyword like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public @interface Version {
  int mayor();
  int minor();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They can receive any primitive types, enums, other annotations and arrays of those previously mentioned. Let’s define an enum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public enum Usage {
  UTILITY,
  DTO,
  DAO,
  SERVICE
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then let’s create another annotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public @interface Info {
  String[] authors();
  Usage usage();
  Version version();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Info(
    authors = {"jsedano", "weirderror"},
    usage = Usage.UTILITY,
    version = @Version(mayor = 1, minor = 0))
public class VeryUtil {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can specify if the annotation needs to be retained by the virtual machine at run time or not; or even if they are to be discarded by the compiler. This is achieved by using a &lt;code&gt;meta-annotation&lt;/code&gt;, meta-annotations are annotations that are applied to another annotations.&lt;/p&gt;

&lt;p&gt;You can also define where the annotation can be used, for example in methods, in constructors and so on.&lt;/p&gt;

&lt;p&gt;Let’s look at how the &lt;strong&gt;@Override&lt;/strong&gt; annotation is defined (@Override is a predefined annotation that is use to mark methods that are using method overriding):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see the meta-annotation &lt;strong&gt;@Target&lt;/strong&gt; is used to say that this particular annotation can only be used above a method declaration and the &lt;strong&gt;@Retention&lt;/strong&gt; annotation is saying that this annotation will not be recorded in the class file and will not be available at runtime.&lt;/p&gt;

&lt;p&gt;In order to actually define functionality for an annotation type we need to implement an &lt;a href="https://dev.to/jsedano/a-custom-annotation-to-apply-currying-in-java-1l68"&gt;AbstractProcessor&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Currying in Java</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Mon, 13 Jun 2022 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/currying-in-java-2hm</link>
      <guid>https://dev.to/jsedano/currying-in-java-2hm</guid>
      <description>&lt;p&gt;Let’s see some examples of how to achieve currying in Java.&lt;/p&gt;

&lt;p&gt;You can find the complete code for this here: &lt;a href="https://github.com/jsedano/examples/blob/main/java-snippets/curry_example.jsh"&gt;curry_example.jsh&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Currying is taking a function with &lt;code&gt;n&lt;/code&gt; parameters and returning a function with one parameter that returns a function with one parameter until you reach the &lt;code&gt;n&lt;/code&gt; parameters of the original function and then you get the result.&lt;/p&gt;

&lt;p&gt;The following method gets the curried version of a method with the signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int methodName(int a, int b)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And returns the curried version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static Function&amp;lt;Integer, Function&amp;lt;Integer, Integer&amp;gt;&amp;gt; toCurry(
    BiFunction&amp;lt;Integer, Integer, Integer&amp;gt; function) {
  return v -&amp;gt; v1 -&amp;gt; function.apply(v, v1);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can use it to get curried versions of such methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var curriedAdd = toCurry(Math::addExact);
var curriedMultiply = toCurry(Math::multiplyExact);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And use them like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System.out.format("curriedAdd(2)(10): %d\n",curriedAdd.apply(2).apply(10));
System.out.format("curriedMultiply(2)(10): %d\n",curriedMultiply.apply(2).apply(10));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the following example we use the curried versions to first add 1 and then multiply by 2 all the elements of a stream&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var add1 = toCurry(Math::addExact).apply(1);
var multiplyBy2 = toCurry(Math::multiplyExact).apply(2);
List.of(0, 1, 2, 3, 4).stream().map(add1).map(multiplyBy2).forEach(System.out::println);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use currying as a form of &lt;code&gt;partial application&lt;/code&gt;, imagine we have the following method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static String wget(
    int connectionTimeout,
    int readTimeout,
    boolean followRedirects,
    String requestMethod,
    String address) {
  try {
    URL url = new URL(address);
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    con.setRequestMethod(requestMethod);
    con.setConnectTimeout(connectionTimeout);
    con.setReadTimeout(readTimeout);
    con.setInstanceFollowRedirects(followRedirects);
    return address + " " + con.getResponseCode();
  } catch (Exception e) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    e.printStackTrace(pw);
    String stackTrace = sw.toString();
    return address + " " + stackTrace.substring(0, stackTrace.indexOf("\n"));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method returns the &lt;code&gt;http status&lt;/code&gt; or part of the exception if any was thrown.&lt;/p&gt;

&lt;p&gt;If we use it like that we would have to be setting all the parameters everytime we want to use the function, but if we have a curried version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static Function&amp;lt;Integer, Function&amp;lt;Boolean, Function&amp;lt;String, Function&amp;lt;String, String&amp;gt;&amp;gt;&amp;gt;&amp;gt;
    cwget(int v) {
  return v1 -&amp;gt; v2 -&amp;gt; v3 -&amp;gt; v4 -&amp;gt; wget(v, v1, v2, v3, v4);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could then set the parameters we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var get = cwget(100).apply(100).apply(false).apply("GET");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then just fill the renaming parameter when using the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List.of(
        "https://www.google.com",
        "https://www.wikipedia.org",
        "asdf",
        "https://docs.oracle.com/javase/10/docs/api/java/net/package-summary.html",
        "https://jsedano.dev",
        "https://raw.githubusercontent.com/center-key/clabe-validator/main/clabe.ts")
    .parallelStream()
    .map(get)
    .forEach(System.out::println);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download the complete code from this post here: &lt;a href="https://github.com/jsedano/examples/blob/main/java-snippets/curry_example.jsh"&gt;curry_example.jsh&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Remove duplicates in unordered array with Java using streams</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Sat, 28 May 2022 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/remove-duplicates-in-unordered-array-with-java-using-streams-4imc</link>
      <guid>https://dev.to/jsedano/remove-duplicates-in-unordered-array-with-java-using-streams-4imc</guid>
      <description>&lt;p&gt;Heres how to remove duplicates from an unordered primitive int array on Java using streams.&lt;/p&gt;

&lt;p&gt;You can find the complete code for this here: &lt;a href="https://github.com/jsedano/examples/blob/main/java-snippets/remove_dupes_unordered_the_smart_way.jsh"&gt;remove_dupes_unordered_the_smart_way.jsh&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Consider the following straight forward problem, you receive a primitive int array and you need to return a new array only containing the unique elements.&lt;/p&gt;

&lt;p&gt;Because we are using &lt;code&gt;streams&lt;/code&gt; since 2014 and we know that a &lt;code&gt;Set&lt;/code&gt; does not accept duplicates, we only need to collect the array into a set and back into an array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int[] removeDupes(int arr[]) {
    return Arrays.stream(arr)
        .boxed()
        .collect(Collectors.toSet()).stream()
        .mapToInt(Integer::intValue).toArray();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;boxed&lt;/code&gt; method just returns an Integer stream instead of a primitive one.&lt;/p&gt;

&lt;p&gt;Download the complete code from this post here: &lt;a href="https://github.com/jsedano/examples/blob/main/java-snippets/remove_dupes_unordered_the_smart_way.jsh"&gt;remove_dupes_unordered_the_smart_way.jsh&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Remove duplicates in ordered array Java</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Mon, 05 Jul 2021 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/remove-duplicates-in-ordered-array-java-20d4</link>
      <guid>https://dev.to/jsedano/remove-duplicates-in-ordered-array-java-20d4</guid>
      <description>&lt;p&gt;Heres how to remove duplicates from an ordered primitive int array on Java.&lt;/p&gt;

&lt;p&gt;You can find the complete code for this here: &lt;a href="https://github.com/jsedano/examples/blob/main/java-snippets/remove_dupes.jsh"&gt;remove_dupes.jsh&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Consider the following problem, you have to remove the duplicates from an ordered integer array &lt;code&gt;in place&lt;/code&gt;. Since you cant actually change the length of a primitive array in java without declaring a new one, you will return the new length the array would have without the duplicates.&lt;/p&gt;

&lt;p&gt;In order to solve this in O(n) time and O(1) space we are going to use a &lt;code&gt;two pointer technique&lt;/code&gt;. We will have &lt;code&gt;j&lt;/code&gt; that will increase by one in every iteration and &lt;code&gt;i&lt;/code&gt; which will increase only if its different from the value which j points to, ignoring every duplicate found.&lt;/p&gt;

&lt;p&gt;This doesnt account for a null, or less than a lenght 2 array (in which case we could start j at 0).&lt;/p&gt;

&lt;p&gt;The pre-increment could be less readable but just remember that &lt;code&gt;++variable&lt;/code&gt; means we are increasing first and then using the variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int removeDupes(int arr[]) {
    int i = 0;
    for(int j = 1; j &amp;lt; arr.length; j++) {
        if(arr[i] != arr[j]) {
            arr[++i] = arr[j];
        }
    }
    return ++i;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download the complete code from this post here: &lt;a href="https://github.com/jsedano/examples/blob/main/java-snippets/remove_dupes.jsh"&gt;remove_dupes.jsh&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Binary search trees</title>
      <dc:creator>Juan Sedano</dc:creator>
      <pubDate>Sun, 30 May 2021 06:00:00 +0000</pubDate>
      <link>https://dev.to/jsedano/binary-search-trees-ahi</link>
      <guid>https://dev.to/jsedano/binary-search-trees-ahi</guid>
      <description>&lt;p&gt;A &lt;code&gt;binary search tree&lt;/code&gt; is a &lt;code&gt;binary tree&lt;/code&gt; where the left subtree has smaller elements and the right subtree has larger elements.&lt;/p&gt;

&lt;p&gt;You can find the complete code for this and other data structures here: &lt;a href="https://github.com/jsedano/examples/tree/main/data-structures-and-algorithms"&gt;data structures and algorithms&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a tree anyway
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;tree&lt;/code&gt; is an undirected graph that satisfies any of the following definitions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Acyclic connected graph.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u-XqMDLE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jsedano.dev/assets/images/binary-search-trees/acyclic_connected_graph.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u-XqMDLE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jsedano.dev/assets/images/binary-search-trees/acyclic_connected_graph.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connected graph with N nodes and N-1 edges.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0qMCBI2N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jsedano.dev/assets/images/binary-search-trees/n_nodes_n-1_edges.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0qMCBI2N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jsedano.dev/assets/images/binary-search-trees/n_nodes_n-1_edges.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2 vertices 1 path (A graph in which any 2 vertices are connected by just one path).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YXqcIRsQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jsedano.dev/assets/images/binary-search-trees/2_vertices_one_path.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YXqcIRsQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jsedano.dev/assets/images/binary-search-trees/2_vertices_one_path.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stuff we have to know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Rooted tree:&lt;/strong&gt; Theres a root node and we hold a reference to it, we can choose any node as the root node.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Root node:&lt;/strong&gt; It has no parent, but sometimes is useful to say that the parent of the root node is itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Child:&lt;/strong&gt; Node that extends from another node, a &lt;strong&gt;Parent&lt;/strong&gt; is the inverse of this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Leaf node:&lt;/strong&gt; Node with no children.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Subtree:&lt;/strong&gt; Tree contained in another tree.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pAFW6B3T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jsedano.dev/assets/images/binary-search-trees/rooted_tree.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pAFW6B3T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://jsedano.dev/assets/images/binary-search-trees/rooted_tree.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Binary tree:&lt;/strong&gt; Every node has at most 2 children.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Binary search tree:&lt;/strong&gt; Satisfies the BST invariant, left subtree has smaller elements and right subtree has larger elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complexity of common operations
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Average&lt;/th&gt;
&lt;th&gt;Worst&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert(element)&lt;/td&gt;
&lt;td&gt;O(log(n))&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;remove(element)&lt;/td&gt;
&lt;td&gt;O(log(n))&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;search(element)&lt;/td&gt;
&lt;td&gt;O(log(n))&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Binary Tree Node
&lt;/h3&gt;

&lt;p&gt;This is what the class that we will be using as node looks like (setters and getters omitted).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class BinaryNode&amp;lt;T extends Comparable&amp;lt;? super T&amp;gt;&amp;gt; {
    private BinaryNode&amp;lt;T&amp;gt; leftChild;
    private BinaryNode&amp;lt;T&amp;gt; rightChild;
    private T data;

    public BinaryNode(T data) {
        this.data = data;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Insertion
&lt;/h3&gt;

&lt;p&gt;A common theme is that we are going to have a public method and a private method. If &lt;code&gt;rootNode&lt;/code&gt; is null then it means that the tree is empty and we just set that new value as the root node of the tree.&lt;/p&gt;

&lt;p&gt;If the root node already exists we call our private insertion method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public boolean insert(T data) {
    if(rootNode == null) {
        rootNode = new BinaryNode&amp;lt;&amp;gt;(data);
        length++;
        return true;
    }
    return insert(new BinaryNode&amp;lt;T&amp;gt;(data), rootNode);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we make sure to comply with the BST invariant and traverse the tree accordingly, smaller elements on the left, larger elements on the right.&lt;/p&gt;

&lt;p&gt;If we find a leaf node then we set the new node as the child, incrementing the length of the tree and returning true to signify that the insertion was successful.&lt;/p&gt;

&lt;p&gt;This implementation of the BST wont allow for duplicates, if we find one we return false.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private boolean insert(BinaryNode&amp;lt;T&amp;gt; newNode, BinaryNode&amp;lt;T&amp;gt; node) {
    if(newNode.getData().compareTo(node.getData()) &amp;lt; 0) {
        if(node.getLeftChild() == null) {
            node.setLeftChild(newNode);
            length ++;
            return true;
        }
        return insert(newNode, node.getLeftChild());
    }

    if(newNode.getData().compareTo(node.getData()) &amp;gt; 0) {
        if(node.getRightChild() == null) {
            node.setRightChild(newNode);
            length ++;
            return true;
        }
        return insert(newNode, node.getRightChild());
    }

    return false;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Contains
&lt;/h3&gt;

&lt;p&gt;This method will let us know if a value is present in our BST, we have a public method that receives the value to look for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public boolean contains(T data){
    return contains(data, rootNode);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we have a private method that goes inside the tree looking for the value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private boolean contains(T data, BinaryNode&amp;lt;T&amp;gt; node) {
    if(node == null) {
        return false;
    }

    if(data.compareTo(node.getData()) &amp;lt; 0) {
        return contains(data, node.getLeftChild());
    }

    if(data.compareTo(node.getData()) &amp;gt; 0) {
        return contains(data, node.getRightChild());
    }

    return true;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Removal
&lt;/h3&gt;

&lt;p&gt;In the public version of &lt;code&gt;remove&lt;/code&gt; we receive the value to remove, we save the current size of the tree and then we call the recursive private version, if the new size is different then it means the value was removed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public boolean remove(T data) {
    int originalLength = length;
    rootNode = remove(data, rootNode);
    return originalLength != length;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The recursive removal is very interesting, as we traverse the tree the recursive method also returns the correct child for the parent node. For example if we are going inside the right sub tree we do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node.setRightChild(remove(data, node.getRightChild()));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we never find the value we want to remove we are just re-setting the children of the nodes we are traversing, but if we find a match we need to account for three cases.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The node we want to remove is a leaf node.&lt;/li&gt;
&lt;li&gt;Has only a left or right child.&lt;/li&gt;
&lt;li&gt;Has both children.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the first two cases we just return the opposite child, for example this is the case where the left child is null:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(node.getLeftChild() == null) {
    BinaryNode&amp;lt;T&amp;gt; rightChild = node.getRightChild();
    node.setData(null);
    node = null;
    length--;
    return rightChild;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also handles the case where we have a leaf node, for a node with a right child we would return the left child.&lt;/p&gt;

&lt;p&gt;The last case, where a node has both children is tricky since we have to find a node that complies with the BST invariant.&lt;/p&gt;

&lt;p&gt;There are two ways to ensure we comply with the BST invariant we can either find the leftmost child of the right node or the rightmost of the left node. In this implementation we go for the leftmost node of the right child using the following method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private BinaryNode&amp;lt;T&amp;gt; getLeftmost(BinaryNode&amp;lt;T&amp;gt; node) {
    while(node.getLeftChild() != null) {
        node = node.getLeftChild();
    }
    return node;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that we copy the value to the node we are removing and then go inside the subtree in order to delete the node, since its the leftmost node we know that is going to fall in the case of a removal of a leaf node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BinaryNode&amp;lt;T&amp;gt; tmp = getLeftmost(node.getRightChild());
node.setData(tmp.getData());
node.setRightChild(remove(tmp.getData(), node.getRightChild()));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the complete code for the remove method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private BinaryNode&amp;lt;T&amp;gt; remove(T data, BinaryNode&amp;lt;T&amp;gt; node) {
    if(node == null) {
        return null;
    }

    if(data.compareTo(node.getData()) &amp;lt; 0) {
        node.setLeftChild(remove(data, node.getLeftChild()));

    } else if(data.compareTo(node.getData()) &amp;gt; 0) {
        node.setRightChild(remove(data, node.getRightChild()));

    } else {
        if(node.getLeftChild() == null) {
            BinaryNode&amp;lt;T&amp;gt; rightChild = node.getRightChild();
            node.setData(null);
            node = null;
            length--;
            return rightChild;
        }
        if(node.getRightChild() == null) {
            BinaryNode&amp;lt;T&amp;gt; leftChild = node.getLeftChild();
            node.setData(null);
            node = null;
            length--;
            return leftChild;
        }
        BinaryNode&amp;lt;T&amp;gt; tmp = getLeftmost(node.getRightChild());
        node.setData(tmp.getData());
        node.setRightChild(remove(tmp.getData(), node.getRightChild()));
    }
    return node;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download the complete code for this and other data structures here: &lt;a href="https://github.com/jsedano/examples/tree/main/data-structures-and-algorithms"&gt;data structures and algorithms&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>datastructures</category>
    </item>
  </channel>
</rss>
