Waste-Free Coding: Zero-Cost Abstraction in Java

Waste-Free Coding: Zero-Cost Abstraction in Java

Waste-Free Coding: Zero-Cost Abstraction in Java - Solve an event processing problem by reducing waste in the software stack...

Waste-Free Coding: Zero-Cost Abstraction in Java - Solve an event processing problem by reducing waste in the software stack...

Java is often seen as a memory hog that cannot operate efficiently in low memory environments. My aim is to demonstrate what many think is impossible, that a meaningful java program can operate in almost no memory. The example processes 2.2 million CSV records per second in a 3MB heap with zero GC on a single thread in Java.

You will learn where the main areas of waste exist in a Java application and the patterns that can be employed to reduce them. The concept of zero cost abstraction is introduced, and that many optimizations can be automated at compile time through code generation. A maven plugin simplifies the developer workflow.

Our goal is not high performance, that comes as a by-product of maximizing efficiency. The solution employs Fluxtion which uses a fraction of the resources compared with existing java event processing frameworks.

Computing and the Climate

Climate change and its causes are currently of great concern to many. Computing is a major source of emissions, producing the same carbon footprint as the entire airline industry. In the absence of regulation dictating computing energy consumption we, as engineers, have to assume the responsibility for producing efficient systems balanced against the cost to create them.

On a panel session from InfoQ 2019 in London, Martin Thompson spoke passionately about building energy-efficient computing systems. He noted controlling waste is the critical factor in minimizing energy consumption. Martin's comments resonated with me, as the core philosophy behind Fluxtion is to remove unnecessary resource consumption. That panel session was the inspiration for this article.

Processing Requirements

Requirements for the processing example are:

  • Operate in 3MB of the heap with zero GC
  • Use standard Java libraries only, no "unsafe" optimizations
  • Read a CSV file containing millions of rows of input data
  • Input is a set of unknown events, no pre-loading of data
  • Data rows are heterogeneous types
  • Process each row to calculate multiple aggregate values
  • Calculations are conditional on the row type and data content
  • Apply rules to aggregates and count rule breaches
  • Data is randomly distributed to prevent branch prediction
  • Partition calculations based on row input values
  • Collect and group partitioned calculations into an aggregate view
  • Publish a summary report at the end of file
  • Pure Java solution using high-level functions
  • No JIT warm-up
Example Position and Profit Monitoring

The CSV file contains trades and prices for a range of assets, one record per row. Position and profit calculations for each asset are partitioned in their own memory space. Asset calculations are updated on every matching input event. Profits for all assets will be aggregated into a portfolio profit. Each asset monitors its current position/profit state and records a count if either breaches a pre-set limit. The profit of the portfolio will be monitored and loss breaches counted.

Rules are validated at the asset and portfolio level for each incoming event. Counts of rule breaches are updated as events are streamed into the system.

Row Data Types

AssetPrice - [price: double] [symbol: CharSequence]
Deal       - [price: double] [symbol: CharSequence] [size: int]

Sample Data

The CSV file has a header lines for each type to allow dynamic column position to field mapping. Each row is preceded with the simple class name of the target type to marshal into. A sample set of records including header:

Deal,symbol,size,price
AssetPrice,symbol,price
AssetPrice,FORD,15.0284
AssetPrice,APPL,16.4255
Deal,AMZN,-2000,15.9354

Calculation Description

Asset calculations are partitioned by a symbol and then gathered into a portfolio calculation.

Partitioned Asset Calculations

asset position  = sum(Deal::size)
deal cash value = (Deal::price) X (Deal::size) X -1
cash position   = sum(deal cash value)
mark to market  = (asset position) X (AssetPrice::price)
profit          = (asset mark to market) + (cash position)

Portfolio Calculations

portfolio profit = sum(asset profit)

Monitoring Rules

asset loss > 2,000
asset position outside of range +- 200
portfolio loss > 10,000

NOTE:

  1. A count is made when a notifier indicates a rule breach. The notifier only fires on the first breach until it is reset. The notifier is reset when the rule becomes valid again.
  2. A positive deal::size is a buy, a negative value a sell.
Execution Environment

To ensure memory requirements are met (zero GC and 3MB heap), the Epsilon no-op garbage collector is used, with a max heap size of 3MB. If more than 3MB of memory is allocated throughout the life of the process, the JVM will immediately exit with an out of memory error.

To run the sample: clone from git, and in the root of the trading-monitor project, run the jar file in the dist directory to generate a test data file of 4 million rows.

git clone --branch  article_may2019 https://github.com/gregv12/articles.git
cd articles/2019/may/trading-monitor/
jdk-12.0.1\bin\java.exe -jar dist\tradingmonitor.jar 4000000

Input Data

By default. the tradingmonitor.jar processes the data/generated-data.csv file. Using the command above, the input data should have the following characteristics:

Input file    = data/generated-data.csv
Trade count   =   200,000
price updates = 3,800,000
Asset count   =         7
File size     =        96 MB

A utility is provided to generate input data files of different data sizes, see GenerateTestData.java.

Results

To execute the test, run the tradingmonitor.jar with no arguments:

jdk-12.0.1\bin\java.exe -verbose:gc -Xmx3M -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -jar dist\tradingmonitor.jar

Executing the test for 4 million rows the summary results are:

Process row count     =    4 million
Processing time       =    1.815 seconds
Avg row exec time     =  453 nano seconds
Process rate          =    2.205 million records per second
garbage collections   =    0
allocated mem total   = 2857 KB
allocated mem per run =   90 KB
OS                    = windows 10
Processor             = Intel core [email protected]
Memory                = 16 GB
Disk                  = 512GB Samsung SSD PM961 NVMe

NOTE: Results are from the first run without JIT warm-up. After JIT warm-up, the code execution times are approx 10 percent quicker. Total allocated memory is 2.86MB, which includes starting the JVM.

Analysing Epsilon's output, we estimate the app allocates 15 percent of memory for 6 runs, or 90KB per run. There is a good chance the application data will fit inside L1 cache, but more investigations are required here.

Output

The test program loops 6 times. Printing out the results each time, Epsilon records memory statistics at the end of the run.

jdk-11.0.1\bin\java.exe" -server -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC  -Xmx3M -verbose:gc -jar dist\tradingmonitor.jar
[0.014s][info][gc] Non-resizeable heap; start/max: 3M
[0.015s][info][gc] Using TLAB allocation; max: 4096K
[0.016s][info][gc] Elastic TLABs enabled; elasticity: 1.10x
[0.018s][info][gc] Elastic TLABs decay enabled; decay time: 1000ms
[0.019s][info][gc] Using Epsilon
[0.057s][info][gc] Heap: 3M reserved, 3M (100.00%) committed, 0M (5.45%) used
.....
[0.263s][info][gc] Heap: 3M reserved, 3M (100.00%) committed, 2M (73.88%) used
portfolio loss gt 10k count -> 1894405.0
Portfolio PnL:-1919.9455999995407
Assett positions:
-----------------------------
MSFT : AssetTradePos{symbol=MSFT, pnl=-388.0564999999906, assetPos=420.0, mtm=7323.246, cashPos=-7711.302499999991, positionBreaches=156, pnlBreaches=51015}
GOOG : AssetTradePos{symbol=GOOG, pnl=-359.2007000000076, assetPos=319.0, mtm=5135.4215, cashPos=-5494.622200000008, positionBreaches=335, pnlBreaches=104282}
APPL : AssetTradePos{symbol=APPL, pnl=14.577800000011848, assetPos=-600.0, mtm=-9936.42, cashPos=9950.997800000012, positionBreaches=46, pnlBreaches=69790}
ORCL : AssetTradePos{symbol=ORCL, pnl=72.58320000000003, assetPos=-404.0, mtm=-6327.0036, cashPos=6399.5868, positionBreaches=66, pnlBreaches=40570}
FORD : AssetTradePos{symbol=FORD, pnl=-1339.9584999997278, assetPos=1359.0, mtm=21383.457300000002, cashPos=-22723.41579999973, positionBreaches=5, pnlBreaches=116290}
BTMN : AssetTradePos{symbol=BTMN, pnl=579.833700000183, assetPos=-513.0, mtm=-8037.8379, cashPos=8617.671600000183, positionBreaches=29, pnlBreaches=106779}
AMZN : AssetTradePos{symbol=AMZN, pnl=-499.72460000000956, assetPos=79.0, mtm=1249.1322, cashPos=-1748.8568000000096, positionBreaches=68, pnlBreaches=27527}
millis:1814
...
...
starting
portfolio loss gt 10k count -> 1894405.0
Portfolio PnL:-1919.9455999995407
Assett positions:
-----------------------------
MSFT : AssetTradePos{symbol=MSFT, pnl=-388.0564999999906, assetPos=420.0, mtm=7323.246, cashPos=-7711.302499999991, positionBreaches=156, pnlBreaches=51015}
GOOG : AssetTradePos{symbol=GOOG, pnl=-359.2007000000076, assetPos=319.0, mtm=5135.4215, cashPos=-5494.622200000008, positionBreaches=335, pnlBreaches=104282}
APPL : AssetTradePos{symbol=APPL, pnl=14.577800000011848, assetPos=-600.0, mtm=-9936.42, cashPos=9950.997800000012, positionBreaches=46, pnlBreaches=69790}
ORCL : AssetTradePos{symbol=ORCL, pnl=72.58320000000003, assetPos=-404.0, mtm=-6327.0036, cashPos=6399.5868, positionBreaches=66, pnlBreaches=40570}
FORD : AssetTradePos{symbol=FORD, pnl=-1339.9584999997278, assetPos=1359.0, mtm=21383.457300000002, cashPos=-22723.41579999973, positionBreaches=5, pnlBreaches=116290}
BTMN : AssetTradePos{symbol=BTMN, pnl=579.833700000183, assetPos=-513.0, mtm=-8037.8379, cashPos=8617.671600000183, positionBreaches=29, pnlBreaches=106779}
AMZN : AssetTradePos{symbol=AMZN, pnl=-499.72460000000956, assetPos=79.0, mtm=1249.1322, cashPos=-1748.8568000000096, positionBreaches=68, pnlBreaches=27527}
millis:1513
[14.870s][info][gc] Total allocated: 2830 KB
[14.871s][info][gc] Average allocation rate: 19030 KB/sec

Waste Hotspots

The table below identifies functions in the processing loop that traditionally create waste and waste avoidance techniques utilized in the example.

Waste Reduction Solutions

The code that implements the event processing is generated using Fluxtion. Generating a solution allows for a zero-cost abstraction approach where the compiled solution has minimum overhead. The programmer describes the desired behavior, and at build time, an optimized solution is generated that meets the requirements. For this example, the generated code can be viewed here.

The Maven POM contains a profile for rebuilding the generated files using the Fluxtion Maven plugin executed with the following command:

mvn -Pfluxtion install

File Reading

Data is extracted from the input file as a series of CharEvents and published to the CSV-type marshaller. Each character is individually read from the file and pushed into a CharEvent. As the same CharEvent instance is re-used, no memory is allocated after initialization. The logic for streaming CharEvents is located in the CharStreamer class. The whole 96 MB file can be read with almost zero memory allocated on the heap by the application.

CSV Processing

Adding a @CsvMarshaller to a javabean notifies Fluxtion to generate a CSV parser at build time. Fluxtion scans application classes for the @CsvMarshaller annotation and generates marshallers as part of the build process. For example, see AssetPrice.java, which results in the generation of AssetPriceCsvDecoder0. The decoder processes CharEvents and marshalls the row data into a target instance.

The generated CSV parsers employ the strategies outlined in the table above, avoiding any unnecessary memory allocation and re-using object instances for each row processed:

  • A single re-usable instance of a characters buffer stores the row characters
  • A flyweight re-usable instance is the target for the marshaled row data
  • Conversions are performed directly from a CharSequence into target types without intermediate object creation.
  • If CharSequences are used in the target instance field, then no strings are created; a flyweight Charsequence is used.

For example, a waste-free char targets field conversion and sees the upateTarget() method in a AssetPriceCsvDecoder0; this is generated by Fluxtion:

private boolean updateTarget() {
  try {
    updateFieldIndex();
    fieldIndex = fieldName_price;
    setPrice.subSequence(delimIndex[fieldName_price], delimIndex[fieldName_price + 1] - 1);
    target.setPrice(atod(setPrice));
    fieldIndex = fieldName_symbol;
    setSymbol.subSequence(delimIndex[fieldName_symbol], delimIndex[fieldName_symbol + 1] - 1);
    target.setSymbol(setSymbol);
  } catch (Exception e) {
....
  }
  return true;
}

Calculations

This builder describes the asset calculation using the Fluxtion streaming API. The declarative form is similar to the Java stream API but builds real-time event processing graphs. Methods marked with the annotation @SepBuilder are invoked by the Maven plugin to generate a static event processor. The code below describes the calculations for an asset, see FluxtionBuilder:

@SepBuilder(name = "SymbolTradeMonitor",
            packageName = "com.fluxtion.examples.tradingmonitor.generated.symbol",
            outputDir = "src/main/java",
            cleanOutputDir = true
    )
    public void buildAssetAnalyser(SEPConfig cfg) {
        //entry points subsrcibe to events
        Wrapper<Deal> deals = select(Deal.class);
        Wrapper<AssetPrice> prices = select(AssetPrice.class);
        //result collector, and republish as an event source
        AssetTradePos results = cfg.addPublicNode(new AssetTradePos(), "assetTradePos");
        eventSource(results);
        //calculate derived values
        Wrapper<Number> cashPosition = deals
                .map(multiply(), Deal::getSize, Deal::getPrice)
                .map(multiply(), -1)
                .map(cumSum());
        Wrapper<Number> pos = deals.map(cumSum(), Deal::getSize);
        Wrapper<Number> mtm = pos.map(multiply(), arg(prices, AssetPrice::getPrice));
        Wrapper<Number> pnl = add(mtm, cashPosition);
        //collect into results
        cashPosition.push(results::setCashPos);
        pos.push(results::setAssetPos);
        mtm.push(results::setMtm);
        pnl.push(results::setPnl);
        deals.map(count()).push(results::setDealsProcessed);
        prices.map(count()).push(results::setPricesProcessed);
        //add some rules - only fires on first breach
        pnl.filter(lt(-200))
                .notifyOnChange(true)
                .map(count())
                .push(results::setPnlBreaches);
        pos.filter(outsideBand(-200, 200))
                .notifyOnChange(true)
                .map(count())
                .push(results::setPositionBreaches);
        //human readable names to nodes in generated code - not required 
        deals.id("deals");
        prices.id("prices");
        cashPosition.id("cashPos");
        pos.id("assetPos");
        mtm.id("mtm");
        pnl.id("pnl");
    }

The functional description is converted into an efficient imperative form for execution. A generated event processor, SymbolTradeMonitor, is the entry point for AssetPrice and Deal events. Generated helper classes are used by the event processor to calculate the aggregates; the helper classes are here.

The processor receives events from the partitioner and invokes helper functions to extract data and call calculation functions, storing aggregate results in nodes. Aggregate values are pushed into fields of the results instance, AssetTradePos. No intermediate objects are created; any primitive calculation is handled without auto-boxing. Calculation nodes reference data from parent instances, no data objects are moved around the graph during execution. Once the graph is initialized, there are no memory allocations when an event is processed.

An image representing the processing graph for an asset calculation is generated at the same time as the code, which can be seen below:

A similar set of calculations is described for the portfolio in the FluxtionBuilderbuilder class buildPortfolioAnalyser method, generating a PortfolioTradeMonitor event.

The AssetTradePos is published from a SymbolTradeMonitor to the PortfolioTradeMonitor.

The generated files for the portfolio calculations are located here.

Partitioning and Gathering

All calculations, partitioning and gathering operations happen in the same single thread; no locks are required. Immutable objects are not required as there are no concurrency issues to handle. The marshaled events have an isolated private scope, allowing safe re-use of instances as the generated event processors control the lifecycle of the instances during event processing.

System Data Flow

The diagram below shows the complete data flow for the system from bytes on a disk to the published summary report. The purple boxes are generated as part of the build; blue boxes are re-usable classes.

Conclusion

In this article, I have shown how it is possible to solve a complex event handling problem in Java with almost no waste. High-level functions were utilized in a declarative/functional approach to describing desired behavior and the generated event processors met the requirements of the description. A simple annotation triggered the marshaller generation. The generated code is a simple imperative code that the JIT can optimize easily. No unnecessary memory allocations are made, and instances are re-used as much as possible.

Following this approach, high-performance solutions with low resource consumption are within the grasp of the average programmer. Traditionally, only specialist engineers with many years of experience could achieve these results.

Although novel in Java, this approach is familiar in other languages, commonly known as zero-cost abstraction.

With today's cloud-based computing environments, resources are charged per unit consumed. Any solution that saves energy will also have a positive benefit on the company.

Java to C# – C# to Java

Java to C# – C# to Java

In this post, we bring you a much needed Rosetta Stone — an explanatory bridge between these two technologies

Originally published by Andy Macdonald at https://medium.com
Java and C# are incredibly similar. Both languages are somewhat derived from C++ and from similar first principles.

Java was developed in 1995 to create a language with a simpler programming model than C++ while still preserving some of the same syntax of the language to facilitate developers transitioning to it.

C# was developed in 2000 by Microsoft as part of its .NET drive in order to develop a language and set of technologies that could address some of the perceived weaknesses of the C++ language. It was also developed with quite heavy “inspiration” from the Java language.

Despite the similarities between the languages and sharing some common ground, transitioning from one technology to the other for a developer well-practised in one technology can be quite tricky.

Innovation happens best when there is collaboration between people of different mindsets — yet users of C# and Java can be somewhat tribalistic.

To that end, I thought it would be useful to put together a sort of guide to help people thinking about or starting to transition between these two technologies. It would also be nice in some way to facilitate a bit more collaboration between these two worlds — hopefully to do my bit to reduce the needless gulf that exists between them.

Some of the similarities right off the bat:

Java is a language that runs in a virtual machine environment (JVM) and runs bytecode that the Java compiler generates.

For C#, the situation is similar. It is a language that runs on the .NET framework and the CLR runtime. It uses a similar intermediary language to Java bytecode called MSIL which gets run via CLR.

Naming and Conventions

Some of the key and most immediately obvious differences in nomenclature, syntax, and conventions are:

  • “Projects” (Java) — “Solutions” (C#)
  • In Java, methods use lowerCamelCase (bar.doAThing()), whilst in C# public methods use PascalCase (bar.DoAThing())
  • In C#, interfaces are always prefixed with an I, as in IUserService<T>, instead of UserService<T>** **in Java
  • In Java, a string is a String** **— in C# a string is a string
  • “POJO” (Java) — “POCO” (C#)
  • Packages (Java) — Namespaces (C#)

Package (Java)

package dev.andymacdonald;

// Code goes here

Namespace (C#)

namespace Dev.AndyMacdonald 
{
  // Code goes here
}

Syntax

**Java has <strong>final</strong> variables — C# has **<strong>readonly</strong>

A key difference here is that Java final variables can be assigned once anywhere in the class, whereas C#’s readonly variables can only be assigned in the constructor.

C# has <strong>out</strong> and <strong>ref</strong> parameters to allow passing arguments by reference — Java doesn’t

It can manipulate objects and variables by reference, but in a method, these arguments are passed by a value. With C#, we can override this behaviour with the out and ref keywords.

Annotations (Java) — attributes (C#)

These are basically equivalent concepts and just differ in actual syntax. Both annotations and attributes can be accessed via each language’s respective Reflection API implementation.

Java annotation:

@PersonallyIdentifiable
private String fullName;

C# attribute:

[PersonallyIdentifiable]
private string fullName;

Getters and setters or Project Lombok (Java) — C# properties

C# really overtakes Java here with its built-in properties* *feature. In the standard JDK, there isn’t an equivalent to this, and instead, in Java, getters and setters must be written for each field requiring an accessor.

These are often just generated by the developer with their IDE as a cheat … still a bit tedious, though.

Java getters and setters:


public class Element 
{
   
  private String symbol;   
  private String name;   
  private int atomicNumber;
  public int getAtomicNumber() 
  {
    return this.atomicNumber;
  }
  public String getSymbol() 
  {
    return this.symbol;
  }
  public String getName() 
  {
    return this.name; 
  }
  public void setAtomicNumber(int atomicNumber) 
  {
    this.atomicNumber = atomicNumber;
  }
  public void setName(String name) 
  {
    this.name = name;
  }
  public void setSymbol(String symbol) 
  {
    this.symbol = symbol;
  }
}

Many Java projects incorporate Project Lombok, which adds getters, setters, equals, and hash code (plus other useful boilerplates) at compile time.

Project Lombok — not part of the standard library:

@Getter @Setter
public class Element 
{
   
  private String symbol;   
  private String name;   
  private int atomicNumber;
}

C# built-in properties feature:

public class Element 
{

  public string Symbol { get; set; }     
  public string Name { get; set; }     
  public int AtomicNumber { get; set; }
}

Loops

Java for each loop:

List<Integer> fibNumbers = Arrays.asList(0, 1, 1, 2, 3, 5, 8, 13);
int count = 0;
for (int element: fibNumbers)
{
    count++;
    System.out.println(String.format("Element #%s: %s", count, element));
}
System.out.println(String.format("Number of elements: %s", count));

C# for each loop:

var fibNumbers = new List<int> { 0, 1, 1, 2, 3, 5, 8, 13 };
int count = 0;
foreach (int element in fibNumbers)
{
    count++;
    Console.WriteLine($"Element #{count}: {element}");
}
Console.WriteLine($"Number of elements: {count}");

Implementing interfaces/inheritance

Inheritance and implementing interfaces isn’t drastically different between the two languages. Java uses the extends or implements keywords; C# uses C++ syntax (derivation declaration) B : A for defining inheritance.

Defining and implementing an interface with methods in Java:

package dev.andymacdonald;


import java.util.ArrayList;
import java.util.List;

interface Fish
{
   void swim();
}

class Salmon implements Fish
{

   public void swim()
   {
      System.out.println("Salmon.Fish");
   }
}

class Cod implements Fish
{
   public void swim()
   {
      System.out.println("Cod.Swim");
   }
}

public class Program
{
   public static void main()
   {
      List<Fish> fishes = new ArrayList<>();
      fishes.add(new Salmon());
      fishes.add(new Cod());

      for (Fish fish : fishes)
      {
         fish.swim();
      }
   }
}

Defining and implementing an interface with methods in C#:

using System;
using System.Collections.Generic;

namespace Dev.AndyMacdonald 
{
    interface Fish
    {
        void Swim();
    }
    class Salmon : Fish
    {
        public void Swim()
        {
            Console.WriteLine("Salmon.Fish");
        }
    }
    class Cod : Fish
    {
        public void Swim()
        {
            Console.WriteLine("Cod.Swim");
        }
    }
    class Program
    {
        static void Main()
        {
            List<Fish> fishes = new List<Fish>();
            fishes.Add(new Salmon());
            fishes.Add(new Cod());
            foreach (Fish fish in fishes)
            {
                fish.Swim();
            }
        }
    }
}

Pointers

Quite simply, Java just doesn’t do pointers, whereas in C# it is possible to do pointer arithmetic and manipulation.

 unsafe {
  int a = 25;
  int * ptr = &a;
  Console.WriteLine($"Value of pointer is {*ptr}");
}

IDE

Visual Studio

C# developers traditionally and typically use the Visual Studio IDE. This is a situation borne out of the origins of .NET being a closed-source technology. Microsoft developed Visual Studio** **to be a one-stop shop for all things .NET.

Java went down a different route, offering much more developer choice in tooling from the outset. That’s why there’s a much greater range of IDEs for Java development (e.g., IntelliJ, Eclipse, NetBeans). Gradually the landscape for .NET developers has shifted, and more IDEs and developer choice has been offered over the years.

IntelliJ (Java) — Rider (C#)

Users of JetBrains IDEs will find the transition from one IDE to another very smooth if they choose to make a switch to the respective JetBrains IDE in the technology they are targeting. Keyboard shortcuts, IDE layout, and even some plugins are equivalent or comparable — virtually the same IDE.

Dependency Management

Maven (Java) — NuGet and dotnet CLI (C#)

Maven is a tool responsible for dependency management and the life cycle of the building of typically Java and JVM applications. That said, it is pretty flexible, has 1000s of plugins, and can be used to build applications of other languages, such as PHP and JavaScript.

The configurable unit of maven is a pom.xml file that every maven project has. For a project’s submodules, it is possible to have a pom file per submodule which inherits from a parent. Maven uses a remote server or repository of some kind to host and retrieve packages.

Maven pom.xml file (Java):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.andymacdonald</groupId>
    <artifactId>fish-app</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

At the simplest level, you can test and build a Maven project with the following command:

mvn clean install

And create a package with this:

mvn clean package

And finally, deploy a package like this:

mvn clean deploy

NuGet fulfills a similar, though not identical role in .NET to Maven. NuGet can use a few different configuration files but commonly uses .csproj*. *As with Maven, NuGet uses a server/repository that can host packages.

NuGet .csproj file:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <AssemblyName>MSBuildSample</AssemblyName>
    <OutputPath>Bin\</OutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="helloworld.cs" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="MyDependency" version="1.0.0" />
  </ItemGroup>  
  <Target Name="Build">
    <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
    <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
  </Target>
</Project>

NuGet’s primary role is package management, construction, and deployment. Java developers will notice that it doesn’t really have the same concept of build phases as Maven does. Additionally, .NET developers don’t tend to edit their build files manually as Java developers do with pom.xml files, preferring to manipulate them in their IDE instead.

Packages can be built, packaged, and deployed to NuGet with the following nuget commands:

nuget spec
nuget pack {nuspec file}
nuget push {package file} {apikey} -Source {host url}

If you want to run the tests for your .NET application, you can run the following dotnet CLI command:

dotnet test

The dotnet CLI can also be used as a wrapper around nuget commands.

Application Servers

Apache Tomcat (Java) — IIS (ASP.NET)

Tomcat is an open-source web server and servlet container from the Apache Foundation. Though there are many other application servers used widely in Java, it is a pretty common choice for most enterprise-software companies. It works across pretty much every operating system (e.g., Windows, Unix, Linux, and Mac OS).

.NET projects are typically deployed on IIS, a web server that only runs on Windows. While its portability is limited, it’s a pretty popular choice for Windows developers because of its ease of use and simplicity while still offering some advanced configuration options.

… But Wait!

For .NET Core web applications, you can package them to run as standalone web applications — allowing you to run them like this:

dotnet <app_assembly>.dll

In the same way you can run a Java Spring Boot web*** ***application (which has a self-contained Tomcat server):

java -jar <my-application>.jar

And visit your shiny new web app like this:

http://<serveraddress>:<port>

Libraries and Frameworks

Spring Framework (Java) — ASP.NET (C#)

The Spring Framework is a framework and IoC container for Java. In short, the Spring framework is responsible for instantiating objects (beans) and managing the life cycle of these beans in memory.

Create an ApplicationContext* *(similar to the concept of a Startup in ASP.NET). This example uses Spring Boot:

@SpringBootApplication
public class HumanApplication
{
   public static void main(String[] args) 
   {
      SpringApplication.run(HumanApplication.class, args);
   }
}

Create an interface:

public interface Organ<T>
{  
   void function();
}

Implement the Organ<T> interface:

@Component
public class Heart implements Organ<Heart>
{
    public Heart() {}
    public void function() 
    {
        System.out.println("Buh-dump");
    }
}

Constructor injection of Organ dependencies list into a Human service:

@Service
public class Human 
{
    private static final int MAX_SECONDS_OF_LIFE = 3000;
    private List<Organ> organs;
    public Human(List<Organ> organs) 
    {
        this.organs = organs;
    }
    @PostConstruct
    public void live() 
    {
        for (int i = 0; i < MAX_SECONDS_OF_LIFE; i++) 
        {
            organs.forEach(organ -> organ.function());
        }
    }
}

Run the application …

It’s aliiiiiiive:

Buh-dump
Buh-dump
Buh-dump
Buh-dump
...

Spring also ships with a handy suite of modules and packages.

In the core Spring packages, and in the convention-over-configuration extension to the framework, Spring Boot, useful combinations of existing and bespoke technologies are provided for developers wanting access to common libraries to kickstart a project with all that they may need, rather than having to write or track down these utilities themselves:

  • RestTemplate (spring-web — for constructing REST and HTTP requests)
  • JdbcTemplate (spring-data — for constructing JDBC queries and statements)
  • Spring Security (for creating and managing application security models)
  • ObjectMapper (spring-core — useful utility for mapping POJOs from Jackson)
  • etc.

ASP.NET fulfills a similar role in the world of C#, providing IoC functionality, commonly used technologies, and utilities in a single framework. However, ASP.NET generally only provides IoC functionality for web applications, whereas the Spring Framework provides this for any application type.

In terms of dependency inversion, it is possible to do very similar things in ASP.NET as in Spring.

As before, define the needed interface and concrete implementation:

public interface Organ<T>
{  
   void Function();
}
public class Heart : Organ<Heart>
{
    public Heart() {}
    public void Function() 
    {
        Console.WriteLine("Buh-dump");
    }
}

Invoke functions of injected dependencies:

public class Human
{

   private List<IOrgan> _organs;
 
   public Human(List<IOrgan> organs)
   {
      _organs = organs;
      this.Live();
   }
   public void Live()
   {
      organs.ForEach(organ =>
      {
         organ.Function();
      });
   }
}

Define a Startup and register services:

public class Startup  
{    
  public void ConfigureServices(IServiceCollection services)
  {    
    services.AddTransient<IList<IOrgan>>(p => p.GetServices<IOrgan>().ToList());
  }
}

ASP.NET also fulfills the role of providing many useful libraries and utilities to accelerate development of your project.

Streams (Java) — LINQ (C#)

Both Java and C# have mechanisms to simplify the reduction of data sets — Streams and LINQ.

There are some differences and gaps between the two technologies but if you have familiarity with one, you’ll be able to get up and running fairly quickly with the other.

Java Streams:

List<Student> studentList = Arrays.asList( 
    new Student(1, "John", 18, 1),
    new Student(2, "Steve", 21, 1),
);
List<String> studentNames = studentList.stream()
    .filter(s -> s.getAge() > 18)
    .filter(s -> s.getStandardID() > 0)
    .map(s -> s.getName()).collect(Collectors.toList());
studentNames.forEach(name -> System.out.println(name));

LINQ Query (C#):

IList<Student> studentList = new List<Student>() { 
    new Student() { StudentID = 1, StudentName = "John", Age = 18, StandardID = 1 } ,
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 21, StandardID = 1 }
};
var studentNames = studentList.Where(s => s.Age > 18)
                        .Where(st => st.StandardID > 0)
                        .Select(s => s.StudentName);
foreach(var name in studentNames) {   
    Console.WriteLine(name);
}

Apache Commons (Java) — CommonLibrary.NET (C#)

Apache Commons*** ***provides Java developers with a collection of several independently released, useful components and utilities for the purposes of accelerating development.

If you’re in need of a utility to work with ZIP files or a set of utilities for working with mathematical expressions and formulae, then Apache Commons has you covered.

In a similar way, CommonLibrary.NET covers these bases too — there are some key differences in naming of some components and modules, but for the most part, they are pretty much equivalent in their purpose.

That said, unlike Apache Commons, CommonLibrary.NET is quite old and isn’t very commonly used in projects anymore. If you’re after a continuously updated, curated list of libraries for each respective technology, I highly recommend these two lists:

akullpp/awesome-java

quozd/awesome-dotnet

Testing Libraries

JUnit (Java) — NUnit (C#)

Java’s ever-dependable JUnit library has a direct equivalent in C#.

NUnit has almost equivalent functionality to JUnit and is a popular choice for C# developers.

JUnit:

@Test
public void complexNumberTest()
{
    ComplexNumber result = someCalculation();
    Assert.assertEquals("Real", 5.2, result.getRealPart());
    Assert.assertEquals("Imaginary" 3.9, result.getImaginaryPart());
}

NUnit:

[Test]
public void ComplexNumberTest()
{
    ComplexNumber result = SomeCalculation();
    Assert.Multiple(() =>
    {
        Assert.AreEqual(5.2, result.RealPart, "Real");
        Assert.AreEqual(3.9, result.ImaginaryPart, "Imaginary");
    });
}

(Rumour has it NUnit started life as the JUnit source code modified to run in C#.)

Mockito (Java) — Moq (C#)

As with JUnit and NUnit, comparable functionality exists between Java’s Mockito and C#’s Moq library.

Mockito:

Foo mockFoo = mock(Foo.class);
when(mockFoo.doSomething("ping")).thenReturn(true);

Moq:

var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);

That’s It

Thanks for Reading!

I obviously couldn’t fit every difference, similarity, and detail in this article —* *it’s already far too long.

I hope at least I’ve covered enough ground to make you feel confident to make a switch and see how the other half lives.

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

Java Tutorial for Absolute Beginners

100+ Java Interview Questions and Answers In 2019

Python vs Java: Understand Object Oriented Programming

Angular 7 + Spring Boot CRUD Example

Build a Simple CRUD App with Spring Boot and Vue.js

Java String – String Functions In Java With Examples

Java String – String Functions In Java With Examples

In this post, we will be discussing about a new concept, Java String. String is a sequence of characters. But in Java, a string is an object that represents a sequence of characters. The java.lang.String class is used to create string object.

Originally published by Aayushi Johari at https://www.edureka.co
There are two ways to create a String object:
By string literal : Java String literal is created by using double quotes. For Example: String s=“Welcome”; By new keyword : Java String is created by using a keyword “new”. For example: String s=new String(“Welcome”); It creates two objects (in String pool and in heap) and one reference variable where the variable ‘s’ will refer to the object in the heap.
Now, let us understand the concept of Java String pool.

**Java String Pool: **Java String pool refers to collection of Strings which are stored in heap memory. In this, whenever a new object is created, String pool first checks whether the object is already present in the pool or not. If it is present, then same reference is returned to the variable else new object will be created in the String pool and the respective reference will be returned. Refer to the diagrammatic representation for better understanding:

In the above image, two Strings are created using literal i.e “Apple” and “Mango”. Now, when third String is created with the value “Apple”, instead of creating a new object, the already present object reference is returned. That’s the reason Java String pool came into the picture.

Before we go ahead, One key point I would like to add that unlike other data types in Java, Strings are immutable. By immutable, we mean that Strings are constant, their values cannot be changed after they are created. Because String objects are immutable, they can be shared. For example:

   String str =”abc”;

is equivalent to:

char data[] = {‘a’, ‘b’, ‘c’};
     String str = new String(data);

Let us now look at some of the inbuilt methods in String class.

Java String Methods

Java String length(): The Java String length() method tells the length of the string. It returns count of total number of characters present in the String. For example:

public class Example{
public static void main(String args[]{
String s1="hello";
String s2="whatsup";
System.out.println("string length is: "+s1.length()); 
System.out.println("string length is: "+s2.length());
}}

Here, String length() function will return the length 5 for s1 and 7 for s2 respectively.
Java String compareTo(): The Java String compareTo() method compares the given string with current string. It is a method of* ‘Comparable’* interface which is implemented by String class. Don’t worry, we will be learning about String interfaces later. It either returns positive number, negative number or 0. For example:

public class CompareToExample{
public static void main(String args[]){
String s1="hello";
String s2="hello";
String s3="hemlo";
String s4="flag";
System.out.println(s1.compareTo(s2)); // 0 because both are equal
System.out.println(s1.compareTo(s3)); //-1 because "l" is only one time lower than "m"
System.out.println(s1.compareTo(s4)); // 2 because "h" is 2 times greater than "f"
}} 

This program shows the comparison between the various string. It is noticed that

if s1 > s2, it returns a positive number

if s1 < s2, it returns a negative number

if s1 == s2, it returns 0
**Java String concat() : **The Java String concat() method combines a specific string at the end of another string and ultimately returns a combined string. It is like appending another string. For example:

public class ConcatExample{
public static void main(String args[]){
String s1="hello";
s1=s1.concat("how are you");
System.out.println(s1);
}}

The above code returns “hellohow are you”.
Java String IsEmpty() : This method checks whether the String contains anything or not. If the java String is Empty, it returns true else false. For example:

public class IsEmptyExample{
public static void main(String args[]){
String s1="";
String s2="hello";
System.out.println(s1.isEmpty());      // true
System.out.println(s2.isEmpty());      // false
}}

  • Java String Trim() : The java string trim() method removes the leading and trailing spaces. It checks the unicode value of space character (‘u0020’) before and after the string. If it exists, then removes the spaces and return the omitted string. For example:
public class StringTrimExample{ 
public static void main(String args[]){ 
String s1="  hello   "; 
System.out.println(s1+"how are you");        // without trim() 
System.out.println(s1.trim()+"how are you"); // with trim() 
}}  

In the above code, the first print statement will print “hello how are you” while the second statement will print “hellohow are you” using the trim() function.

  • Java String toLowerCase() : The java string toLowerCase() method converts all the characters of the String to lower case. For example:
public class StringLowerExample{
public static void main(String args[]){
String s1="HELLO HOW Are You?”;
String s1lower=s1.toLowerCase();
System.out.println(s1lower);}
}

The above code will return “hello how are you”.

  • Java String toUpper() : The Java String toUpperCase() method converts all the characters of the String to upper case. For example:
public class StringUpperExample{ 
public static void main(String args[]){ 
String s1="hello how are you"; 
String s1upper=s1.toUpperCase(); 
System.out.println(s1upper); 
}}

The above code will return “HELLO HOW ARE YOU”.
Java String ValueOf(): This method converts different types of values into string.Using this method, you can convert int to string, long to string, Boolean to string, character to string, float to string, double to string, object to string and char array to string. The signature or syntax of string valueOf() method is given below: public static String valueOf(boolean b) public static String valueOf(char c) public static String valueOf(char[] c) public static String valueOf(int i) public static String valueOf(long l) public static String valueOf(float f) public static String valueOf(double d) public static String valueOf(Object o)
Let’s understand this with a programmatic example:

public class StringValueOfExample{
public static void main(String args[]){
int value=20;
String s1=String.valueOf(value);
System.out.println(s1+17);       //concatenating string with 10
}}

In the above code, it concatenates the Java String and gives the output – 2017.
Java String replace(): The Java String replace() method returns a string, replacing all the old characters or CharSequence to new characters. There are 2 ways to replace methods in a Java String.

public class ReplaceExample1{
public static void main(String args[]){
String s1="hello how are you";
String replaceString=s1.replace('h','t');
System.out.println(replaceString); }}

In the above code, it will replace all the occurrences of ‘h’ to ‘t’. Output to the above code will be “tello tow are you”. Let’s see the another type of using replace method in java string:

**Java String replace(CharSequence target, CharSequence replacement) method **:

public class ReplaceExample2{
public static void main(String args[]){
String s1="Hey, welcome to Edureka";
String replaceString=s1.replace("Edureka","Brainforce");
System.out.println(replaceString);
}}

In the above code, it will replace all occurrences of “Edureka” to “Brainforce”. Therefore, the output would be “ Hey, welcome to Brainforce”.
Java String contains() :The java string contains() method searches the sequence of characters in the string. If the sequences of characters are found, then it returns true otherwise returns false. For example:

class ContainsExample{
public static void main(String args[]){
String name=" hello how are you doing";
System.out.println(name.contains("how are you"));  // returns true
System.out.println(name.contains("hello"));        // returns true 
System.out.println(name.contains("fine"));         // returns false 
}}

In the above code, the first two statements will return true as it matches the String whereas the second print statement will return false because the characters are not present in the string.
Java String equals() : The Java String equals() method compares the two given strings on the basis of content of the string i.e Java String representation. If all the characters are matched, it returns true else it will return false. For example:

public class EqualsExample{
public static void main(String args[]){
String s1="hello";
String s2="hello";
String s3="hi";
System.out.println(s1.equalsIgnoreCase(s2));   // returns true
System.out.println(s1.equalsIgnoreCase(s3));   // returns false
}
}

  • **JavaString equalsIgnoreCase(): **This method compares two string on the basis of content but it does not check the case like equals() method. In this method, if the characters match, it returns true else false. For example:
public class EqualsIgnoreCaseExample{
public static void main(String args[]){
String s1="hello";
String s2="HELLO";
String s3="hi";
System.out.println(s1.equalsIgnoreCase(s2));   // returns true
System.out.println(s1.equalsIgnoreCase(s3));   // returns false
}}

In the above code, the first statement will return true because the content is same irrespective of the case. Then, in the second print statement will return false as the content doesn’t match in the respective strings.
**Java String toCharArray(): **This method converts the string into a character array i.e first it will calculate the length of the given Java String including spaces and then create an array of char type with the same content. For example:

StringToCharArrayExample{
public static void main(String args[]){
String s1="Welcome to Edureka";
char[] ch=s1.toCharArray();
for(int i=0;i<ch.length;i++){
System.out.print(ch[i]);
}}}

The above code will return “Welcome to Edureka”.
Java StringGetBytes() : The Java string getBytes() method returns the sequence of bytes or you can say the byte array of the string. For example:

public class StringGetBytesExample {
public static void main(String args[]){
String s1="ABC";
byte[] b=s1.getBytes();
for(int i=0;i<b.length;i++){
System.out.println(b[i]);
}
}}

In the above code, it will return the value 65,66,67.
Java String IsEmpty() : This method checks whether the String is empty or not. If the length of the String is 0, it returns true else false. For example:

public class IsEmptyExample{
public static void main(String args[]) {
String s1="";
String s2="hello";
System.out.prinltn(s1.isEmpty());     // returns true
System.out.prinltn(s2.isEmpty());     // returns false
}}

In the above code, the first print statement will return true as it does not contain anything while the second print statement will return false.
Java String endsWith() : The Java String endsWith() method checks if this string ends with the given suffix. If it returns with the given suffix, it will return true else returns false. For example:

public class EndsWithExample{
public static void main(String args[]) {
String s1="hello how are you”;
System.out.println(s1.endsWith("u"));       // returns true
System.out.println(s1.endsWith("you"));     // returns true  
System.out.println(s1.endsWith("how"));     // returns false
}}

This is not the end. There are more Java String methods that will help you make your code simpler.

Moving on, Java String class implements three interfaces, namely – Serializable, Comparable and CharSequence.

Since, Java String is immutable and final, so a new String is created whenever we do String manipulation. As String manipulations are resource consuming, Java provides two utility classes: StringBuffer and StringBuilder.

Let us understand the difference between these two utility classes:
StringBuffer and StringBuilder are mutable classes. StringBuffer operations are thread-safe and synchronized whereas StringBuilder operations are not thread-safe.StringBuffer is to be used when multiple threads are working on same String and StringBuilder in the single threaded environment.StringBuilder performance is faster when compared to StringBuffer because of no overhead of synchronized.
I hope you guys are clear with Java String, how they are created, their different methods and interfaces. I would recommend you to try all the Java String examples. Do read my next blog on Java Interview Questions which will help you set apart in the interview process.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

Top 4 Spring Annotations for Java Developer in 2019

Java Tutorial for Absolute Beginners

100+ Java Interview Questions and Answers In 2019

Python vs Java: Understand Object Oriented Programming

Java Enum Tutorial - Enumeration in Java Explained

Java Enum Tutorial - Enumeration in Java Explained

This video on Java Enum Tutorial will provide you with detailed knowledge about Enumeration in Java along with real times examples for better understanding.

Java Enum Tutorial | Enumeration in Java Explained | Java Tutorial For Beginners

This informative video will include the following.

00:21 Agenda

00:55 What is Enum?

01:22 Why we need Enum?

06:45 Differences between Class and Enum

07:26 Syntax of Enum

07:43 Practical Examples of Enum

15:40 Advantages of using Enum

16:10 Enum Usecase: Rock Paper Scissor Game