Monday, 23 February 2026

Python for Java developers

We’re pleased to welcome our guest blogger, Nikos Vaggalis. Nikos is a journalist at i-programmer and a seasoned software engineer with extensive hands-on experience across a wide range of technologies. With a career that bridges technical journalism and real-world software development, he brings a uniquely informed perspective - grounded in both industry practice and analytical insight.

You can explore more of Nikos’ published work in this collection of his articles. 

Python. Even if you close your eyes and try to ignore it, you really can’t; it’s everywhere, especially in the AI and Data Science fields. Therefore, it has become a necessity to get to know it, even if you’re a Java developer enjoying its rich and large language ecosystem. Despite the fact that lately Java has been powered up with great AI libraries like LangChain4j, which make it easy to build AI-powered applications, in order to tap into the full, unconstrained pool of AI capabilities, you still need to go to Python.

Of course, to use Python for AI and other advanced use cases, you have to first go through the basics. But no worries, as help is on the way. I had the privilege of becoming a beta tester of Geekuni’s Python Essentials, a brand-new course for intermediate-level programmers who know how to program in a different programming language but are new to Python.

Therefore, this tutorial is based on the course and works by converting a few but crucial selected excerpts from Python to Java. As such, it is addressed to programmers who come from a Java background and want to learn Python, but it works the other way too, that is, for Pythonistas looking at Java. So let’s begin!

In Python, indentation is meaningful

For most languages this is what developers use to help other developers (or themselves in 6 months) easily identify sections of code. In the case of Python, indentation actually defines compound statements in the way that { curly braces } do for languages like C:

if (x > 0) {
    printf("x is positive\n");
    printf("x squared is %d\n", x * x);
}

and begin and end do for Pascal:

if x > 0 then
begin
    writeln('x is positive');
    writeln('x squared is ', x * x);
end;

In Python an if statement looks like:

if x > 0:
    print('x is positive')
    print('x squared is', x**2)

print('We are out of the if statement now')

In Java of course you use braces.

Polymorphism with strings, and introducing the REPL

We’ll find out the various ways of representing strings by using Python’s REPL (Read-Eval-Print Loop) as a hands-on tool for learning these concepts interactively.

Just open a terminal and run python3 at the command-line.

$ python3

You can then type things at the prompt, press ENTER and see any output on the following line. For example:

>>> name = "Zachary"
>>> print("Hello, " + name)
Hello, Zachary

In summary: it Reads what you typed; Evaluates that string (which means, it runs it as a Python command); Prints any output (there was only output in the case of the print statement in this example); and Loops back to reading the next line you type.

Now you can use the REPL to experiment with the two separate concepts we’re covering here. The first is polymorphism - where we see an operator (or function) behaving differently depending on its arguments. For example:

>>> print(2 + 3)
5
>>> print('foo' + 'bar')
foobar

In the first case it’s adding the arguments, and in the second, it’s concatenating them. The action of the operator is determined by the types of its arguments.

Now, look at the * operator between numbers and strings.

For example:

>>> print(2 * 3);
6
>>> print("1" * 5);
11111

Java Equivalent

In Java you don’t normally have a REPL because it is a compiled language… or can you? Yes you can, with JBang and its JShell scripting. JShell, Java’s Read-Eval-Print-Loop (REPL) tool (available since JDK 9), allows programmers to quickly test code snippets, explore APIs, and incrementally construct code, providing immediate feedback.

You can download and install Jbang, or you can upload it straight into your browser through the “JBang powered Jupyter Environment”. No JDK install. No account. No IDE. Just head over to TryJbang which we’re going to use for running our Java code as painlessly as possible.

Here’s the equivalent Java code - paste each block into the JBang editor and click run.

String name = "Zachary";
System.out.println("Hello, " + name );
2 + 3;
"foo" + "bar";
2 * 3;
System.out.println("1".repeat(5));

You’ll notice straight away that in Java you have to declare your variables’ types, such as String name=, which starts life as a String and dies as a String. In contrast, Python is dynamically typed and a variable can be a String or a Number or another data type.

Also notice Python’s string repetition example of:

print("1" * 5);

which in Java ends up as:

System.out.println("1".repeat(5));

That is because Java does not overload the * operator for string repetition (unlike Python), requiring the String.repeat() method for this functionality.

Functions

In this exercise we experiment with implementing a function in Python.

As mentioned earlier, indentation defines compound statements in the way that curly braces do so in languages like C. For example - a one line compound statement:

def square(n):
    return n ** 2
>>> square(3)
9

There are three compound statements in the following example - the if block, the else block and also the def block which contains them:

def is_even(n):
    if n % 2:
        print(f"Sorry, {n} is odd")
        return False
    else:
        print(f"Yay! {n} is even")
        return True
>>> is_even(1)
Sorry, 1 is odd
False
>>> is_even(2)
Yay! 2 is even
True

Here’s an example of a recursive function which calls itself:

import math

def num_squares(n):
    """Return the number of squares up to, and including, n
    """
    if n == 1:
        return 0
    return num_squares(n-1) + (
        1 if math.sqrt(n).is_integer() else 0
    )
>>> num_squares(9)
2

Java Equivalent

In Java, the first example would be implemented as a method within a class, specifying int as the parameter type and the return type:

public class FunctionConversion {

    public static int square(int n) {
        return n * n;
    }

    public static void main(String[] args) {
        int result = square(3);
        System.out.println(result); // Output: 9
    }
}

FunctionConversion.main(null);

The second example. In Java, conditional logic uses parentheses around the condition and { curly braces } to delimit the code block for the if and else statements, while output is handled using System.out.println():

public class FunctionConversion {

    public static boolean isEven(int n) {
        // In Python:
        // - 'if n % 2:' is true if the remainder is non-zero
        if (n % 2 != 0) {
            System.out.println("Sorry, " + n + " is odd");
            return false;
        } else {
            System.out.println("Yay! " + n + " is even");
            return true;
        }
    }

    public static void main(String[] args) {
        isEven(3);
        // Output: Sorry, 3 is odd

        isEven(2);
        // Output: Yay! 2 is even
    }
}

FunctionConversion.main(null);

Third example with recursion. In Java, you use Math.sqrt() to calculate the square root. To check if the result is an integer, you can compare the value to its mathematical floor (Math.floor).

import java.lang.Math;

public class FunctionConversion {

    public static int numSquares(int n) {
        if (n == 1) {
            return 0;
        }
        double root = Math.sqrt(n);

        // Determine if the root is an integer
        // In Python: 'is_integer()'
        int addValue = (root == Math.floor(root)) ? 1 : 0;

        // Recursive call
        return numSquares(n - 1) + addValue;
    }

    public static void main(String[] args) {
        int result = numSquares(9);
        System.out.println(result); // Output: 2
    }
}

FunctionConversion.main(null);

Looking at the Python and Java examples side by side, you can’t help but think that Java’s solutions are more verbose than Python’s.

Making a list with the range function

In this exercise we learn about Python’s range class and how we can use it to make a list.

Let’s start by creating a range object:

>>> range(10)
range(0, 10)

This object represents the integers matching x: 0 <= x < 10, namely 0, 1, ... 9.

But how do you get a list of the actual numbers?

nums = []
for x in range(10):
    nums.append(x)
>>> nums
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

The code above introduced you to Python’s append method of a list. It works, but it’s a bit clunky.

Happily, this can be done in one line using the list constructor which takes (in this case) the range object as an argument and returns a list of its elements.

>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Java Equivalent

In Java, the first example requires defining a for loop with explicit initialization, termination condition, and increment, and using a generic ArrayList to hold the resulting numbers.

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

public class RangeConversion {

    public static void main(String[] args) {
        // In Python: nums = []
        List<Integer> nums = new ArrayList<>();

        // In Python: range(10)
        for (int x = 0; x < 10; x++) {
            // In Python: .append(x))
            nums.add(x);
        }

        // Print the result to the console
        System.out.println(nums);

    }
}

RangeConversion.main(null);

Or in modern Java, the second example of Python’s list(range(10)) becomes:

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class RangeConversion {
    public static void main(String[] args) {
        // Creates a List<Integer> of 0 through to 9
        List<Integer> list = IntStream.range(0, 10)
                             .boxed()
                             .collect(Collectors.toList());

        System.out.println(list);
    }
}

RangeConversion.main(null);

Lambdas (of course)

In this exercise we learn how to use lambda functions, a special type of function which is more concise for simple tasks.

First of all, here’s an example of a lambda function which takes a variable x, and returns x + 1:

lambda x: x + 1

and here’s the same function being called:

>>> (lambda x: x + 1)(2)
3

And this is the same function being assigned to a variable, and then called:

>>> f = lambda x: x + 1
>>> f(2)
3

When you run it like that, you won’t be surprised that the lambda function with the code lambda x: x + 1 has the same functionality as the function:

def increment(x):
    return x + 1

with the main difference to the caller being the name:

>>> f.__name__
'<lambda>'
>>> increment.__name__
'increment'

The main difference between writing a lambda to a function is that a lambda can only contain a single expression. What’s an expression?

For the statement:

x = 2*(3 + 5)

2*(3 + 5) is the expression.

Python’s lambdas use the programming pattern which comes from lambda calculus - namely functional programming.

What’s functional programming? Unlike procedural programming, where a block of code is a sequence of statements, including assignments which are creating variables or changing their values:

x = 1
y = 2
x += y

code in functional programming is just an expression - the code you can see on the right hand side of the = assignment operator.

Java Equivalent

The Python lambda function conversion in Java is achieved using Lambda Expressions, a feature introduced in Java 8 to support functional programming. In Java, a lambda expression is a concise way to create an instance of a functional interface (an interface with exactly one abstract method).

So this requires defining a functional interface to serve as the target type for the lambda. We can define a simple interface, or use a built-in one like IntUnaryOperator (for operations on a single integer operand that return an integer result):

import java.util.function.IntUnaryOperator;

public class LambdaConversion {

    public static void main(String[] args) {
        // In Python: f = lambda x: x + 1
        IntUnaryOperator increment = (x) -> x + 1;

        // In Python: (lambda x: x + 1)(2)
        int result = increment.applyAsInt(2);

        System.out.println(result); // Output: 3
    }
}

LambdaConversion.main(null)

Key Differences and Java Concepts:

  1. Context: Java code must reside within a class.

  2. Anonymous Nature: Just like Python’s lambda, the Java lambda expression itself is an anonymous method, but it must be assigned to an instance of a functional interface (IntUnaryOperator in this case).

  3. Return Type: In both Python and Java, if the body of the lambda is a single expression, the result of that expression is implicitly returned without needing a return keyword.

Finally - the map operator

Our final example will demonstrate functional programming in action by building on the Lambdas section above.

The map operator takes two arguments - a function and an iterable, and returns an iterator whose elements are the result of applying the function to the elements of the iterable.

In this exercise we’re playing with the capitalize method of the string class:

>>> 'please check for typos!'.capitalize()
'Please check for typos!'

Here’s a function which takes a string and returns the capitalised version of it:

def cap(word):
    return word.capitalize()

Now we can use map to apply this function to a list of words:

>>> uc_words = map(cap, ['this', 'is', 'a', 'test'])
>>> list(uc_words)
['This', 'Is', 'A', 'Test']

Note that the function can also be a lambda:

>>> uc_words = map(
...     lambda w: w.capitalize(), ['this', 'is', 'a', 'test']
... )
>>> list(uc_words)
['This', 'Is', 'A', 'Test']

The Python map() function converts easily to Java using Streams and Lambda Expressions.

Java Equivalent

In Java the functionality of applying a function to every element of an iterable and collecting the results is typically accomplished using the stream().map().collect() pipeline.

So the Java Equivalent of the first example would use the Stream API to perform the transformation:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class MapConversion {

    // Define the capitalization logic as a dedicated method
    // (or use a lambda directly)
    // Note: Java's standard capitalize methods
    // typically handle the first letter only.
    // Mimicking the behavior of Python's .capitalize().
    public static String cap(String word) {
        if (word == null || word.isEmpty()) {
            return word;
        }
        // In Python: word.capitalize()
        // Capitalize first letter, lowercase the rest
        return word.substring(0, 1).toUpperCase()
            + word.substring(1).toLowerCase();
    }

    public static void main(String[] args) {
        List<String> words = Arrays.asList(
            "this", "is", "a", "test"
        );

        // 1. Create a Stream from the list.
        // 2. Use the map to apply 'cap' to each element.
        // 3. Use Collectors.toList() to generate a List.
        List<String> ucWords = words.stream()
            .map(MapConversion::cap)
            .collect(Collectors.toList());

        System.out.println(ucWords);
    }
}

MapConversion.main(null) // Output: [This, Is, A, Test]

Now using the same Lambda Expressions, which Java can use directly in the map operation:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class LambdaMapConversion {

    public static String capitalizeWord(String w) {
        // In Python: w.capitalize()
        // Capitalize first letter, lowercase the rest
        if (w == null || w.isEmpty()) return w;
        return w.substring(0, 1).toUpperCase()
            + w.substring(1).toLowerCase();
    }

    public static void main(String[] args) {
        List<String> words = Arrays.asList(
            "this", "is", "a", "test"
        );

        // The lambda w -> capitalizeWord(w) is the function,
        // is the functional interface required by stream.map()
        List<String> ucWords = words.stream()
            .map(w -> capitalizeWord(w))
            .collect(Collectors.toList());

        System.out.println(ucWords);
    }
}

LambdaMapConversion.main(null) // Output: [This, Is, A, Test]

The End

So in the end, which code is better? Python or Java? I’ll leave the answer up to you. But before answering, take into consideration that with jbang we simplified the syntax of the Java code which saved a few lines and made it cleaner. We also didn’t need to set up a JDK or an IDE on our PC. This workflow modernizes Java and brings it up to par with the facilities other (even dynamic languages) like Python enjoy.

This caps the tutorial. As already mentioned, all the Python examples used come from Geekuni’s Python Essentials course and represent just a fraction of the available material, material which encompasses all aspects of the language.

Tuesday, 20 January 2026

Press Release - Python Essentials

Geekuni Launches "Python Essentials": A 40-Hour, Project-Based Onboarding Program to Accelerate Developer Productivity


January 20, 2026 — Geekuni today announced the launch of Python Essentials, a project-based, 40-hour onboarding course designed for companies that need experienced developers to become productive in Python quickly.


As Python adoption continues to grow across data, infrastructure and backend systems, many organisations are hiring experienced developers transitioning from other languages. However, most available Python training is designed for beginners, requiring experienced developers to spend time on unnecessary introductory material and slowing their path to productivity.

Geekuni’s Python Essentials addresses this gap directly. The program is engineered specifically for experienced software developers who already understand core programming concepts and need a fast, professional-grade path to writing maintainable, production-ready Python.

"Experienced developers need to move beyond basic programming concepts and dive straight into real-world Python as it’s used in professional teams," said Andrew Solomon, Director at Geekuni. "Python Essentials is designed to respect their time and existing expertise, enabling organisations to turn new hires into confident Python contributors in approximately 40 hours of focused study. This approach builds upon our decade of success in providing professionally focussed Perl training to clients as part of their onboarding process."

Rather than videos and extensive reading, Python Essentials is built around a substantial, end-to-end project, where participants develop a production-style application that reflects real engineering workflows. The curriculum emphasizes:

  • Idiomatic Python and its object-oriented design
  • Advanced Language Features: Working comfortably with Python's syntax, control structures, and advanced features, including generators, decorators, and metaclasses
  • Data-Handling Proficiency: Utilizing Pandas and other critical data-handling tools to extract insights from real datasets, reflecting Python’s prominence in data science
  • Writing testable, maintainable code
  • Debugging, understanding and refactoring existing codebases
For CTOs, Engineering Managers, and HR Onboarding Experts, the program integrates directly into corporate onboarding and training pipelines. Geekuni’s corporate training offering provides:

  • Structured, self-paced online delivery suitable for distributed teams
  • Automated, immediate feedback to reduce reliance on senior engineers
  • Integrated mentoring where an expert provides guidance, ensuring clarity and helping students solve problems through code review
  • Progress tracking and completion certificates, giving managers visibility into readiness of the trainee

By focusing on experienced developers, including those with some Python experience, Geekuni enables companies to hire for strong general engineering ability and onboard into Python more quickly, reducing demand on existing team members. With experience as a software developer and familiarity with object-oriented programming in any language, participants finish the course able to confidently deliver Python code from day one.

Enrollment for Python Essentials is now open.

About Geekuni
Geekuni provides focused, structured technical training for experienced professionals needing to rapidly acquire new skills in core programming languages. Our courses are designed to be practical, relevant, and time-efficient - an approach we have successfully applied for over a decade with Perl training for clients such as Booking.com.

Contact
Andrew Solomon
andrew@geekuni.com
https://geekuni.com

Monday, 3 May 2021

The problem learning Perl using Google

Google search isn't always the best way to find what you're looking for, and learning Perl is a case in point. In this article I'll explain the problem of Google search when learning Perl, and the better alternatives to use.


Thursday, 18 July 2019

How to make Perl training part of the onboarding process


...and meet the demand for new developers


Demand for Perl developers far outstrips supply in the current job market, so hiring one can be expensive as well as a headache. Perl is not even the most common language used, so some employers might want to wean themselves off it altogether. But this would mean re-writing their code in a more popular language such as Java or Python – a huge and cumbersome task. The best option, then, is to hire developers in other languages and train them in Perl while onboarding. This has proven successful for large multinational corporations such as Booking.com, who hire new developers at scale and offer them on-the-job Perl training. So, how do you go about things if this is the route you want to take? Geekuni has specialised in training new hires in Perl for a number of years and we’ve gained some valuable insights.


Onboarding challenges

Finding the willing candidates

Why would a developer experienced in other languages want to join your company and start learning Perl from day one? If they’ve managed to get by without it so far, it’s unlikely to be their top priority as they make their next career move. The first hurdle you face, then, is finding good developers who are open to learning Perl.

The eager newbie

Most talented developers joining a company want to get their teeth stuck into the job by showing what they already know. Learning a completely new language from the start not only delays this but also involves asking questions which expose gaps in their knowledge. Onboarders are already busy getting acquainted with the company, its processes and its people. They need space to grow into the role, so the added burden of Perl training can quickly turn into an obstacle that stands in their way.

The overstretched employer

There’s plenty of potential for frustration on the employer’s side, too. The longer it takes for new recruits to become productive, the higher the cost of their onboarding experience. New hires also place demands on teams, slowing down their productivity as they take time from regular duties to show new developers the ropes. And that’s all before you even consider offering them Perl training. Providing Perl training from day one places an additional strain on teams, and this can seriously slow down business. Although outsourcing the training is an option, face-to-face providers are expensive and can make it difficult for team leads to maintain an overview of the trainees’ progress.

Onboarding solutions for plain sailing

Reaching out to the right people

Let’s face it – Perl is not the most popular language. As a result, the best developers might be more open to joining your company to learn Perl if you focus on selling your company, not the language. That said, you can also challenge the perception of Perl as a stagnant language by talking about how it solves problems in the company. Learning Perl should not be presented as a hurdle to joining the company, but a benefit – getting paid to learn something new is a very appealing proposition.

It’s also worth looking closer to home as you probably have a pool of potential Perl talent right under your nose. Second-line support staff generally make good developers and may be eager for the career opportunity. A big advantage, of course, is that onboarding is a lot more straightforward. This type of internal recruitment – where a member of staff leaves one role to take up a completely new role in the same company – is different to cross-training. (Cross-training doesn’t involve a change of job - it's the acquisition of skills and the corresponding expansion of their job description.)

Giving newbies a sense of ownership

It’s important not to overwhelm new recruits during the onboarding process for it to be effective. One way to achieve this is by giving them greater ownership of their learning. Geekuni’s interactive online Perl training does just that. Trainees have more control over the pace of their learning, which allows them to manage their own time while onboarding. It also gives new hires instant feedback, so they don’t have to bother senior developers with all their questions. The training focuses on task-based learning, which lets trainees apply new coding skills to real-life situations. This means they can start making their own contributions to the company’s codebase a lot quicker.

Giving new recruits the opportunity to participate in Perl conferences such as PerlCon and TPC is also a huge help. Full immersion in the world of Perl allows them to make useful contacts and brings them up to date with the latest trends. Such opportunities are not just enriching for trainees, it gives them fresh new perspectives to take back to the company.

An onboarding process that doesn’t sink the ship

Geekuni’s Perl training has also been designed with employers in mind. It takes the weight off busy teams and team leads, freeing up precious resources. At the same time, an effective system of reporting means that team leads and HR can track the progress of trainees with very little effort. This not only makes the onboarding process plain sailing, but also means you can continue with regular business activities full steam ahead. Keeping the relevant stakeholders in the loop helps identify ongoing training needs for new recruits as they complete the onboarding process. What’s more, a standardised approach provides clear-cut criteria for measuring progress and facilitates more consistent training delivery across different teams or departments.

Conclusion


To expand your Perl talent pool, you need to acknowledge the reality of the job market and work around the obstacles this presents. A tried and tested approach is to hire developers in other languages and train them in Perl during the onboarding period. But this, too, requires some adaptation in order to ensure a well-designed and professionally implemented onboarding process. This can only be achieved if relevant stakeholders work together right from the start to set out a clear path to success.

Saturday, 11 May 2019

Cross-training to grow your Perl team

Expanding a company’s Perl operations can be a headache for HR and tech teams alike. Hiring more staff is not always an option and even when it is, finding a Perl developer to walk straight into a new role is hard. A more viable approach for many companies is to offer cross-training into Perl for staff already employed. The problem is that while your developer is cross-training, there’s work which they aren’t doing. Geekuni has been working closely with companies for several years and we’ve gained valuable insights into what works and what doesn’t. The good news is that you can in fact facilitate the smooth running of existing operations while seamlessly growing your Perl talent through cross-training. Here’s what you need to know.




Sunday, 14 October 2018

Growing your Perl Team - BoF

Expanding the dev team is a challenge every successful Perl shop has to face. At the most recent Perl conference I ran a “Birds of Feather” (BoF) where representatives of over a dozen companies and community groups came together to exchange their experience of what works, what doesn’t and general principles which emerged from these discussions. This is a summary of what came from this meeting.


Tuesday, 30 January 2018

The challenge of recruiting Perl developers


Many employers have a real challenge increasing the size of their Perl team. First we’ll work out the reasons recruitment is so difficult for a Perl team, and then we’ll bounce around some ideas on how to overcome these obstacles.