This answer will demonstrate the difference between implementation, api, and compile on a project. 
Let's say I have a project with three Gradle modules:
- app (an Android application)
- myandroidlibrary (an Android library)
- myjavalibrary (a Java library)
app has myandroidlibrary as dependencies. myandroidlibrary has myjavalibrary  as dependencies.

myjavalibrary has a MySecret class
public class MySecret {
    public static String getSecret() {
        return "Money";
    }
}
myandroidlibrary has MyAndroidComponent class that manipulate value from MySecret class.
public class MyAndroidComponent {
    private static String component = MySecret.getSecret();
    public static String getComponent() {
        return "My component: " + component;
    }    
}
Lastly, app is only interested in the value from myandroidlibrary
TextView tvHelloWorld = findViewById(R.id.tv_hello_world);
tvHelloWorld.setText(MyAndroidComponent.getComponent());
Now, let's talk about dependencies...
app need to consume :myandroidlibrary, so in app build.gradle use implementation.
(Note: You can use api/compile too. But hold that thought for a moment.)
dependencies {
    implementation project(':myandroidlibrary')      
}

What do you think myandroidlibrary build.gradle should look like? Which scope we should use?
We have three options:
dependencies {
    // Option #1
    implementation project(':myjavalibrary') 
    // Option #2
    compile project(':myjavalibrary')      
    // Option #3
    api project(':myjavalibrary')           
}

What's the difference between them and what should I be using?
Compile or Api (option #2 or #3)

If you're using compile or api. Our Android Application now able to access myandroidcomponent dependency, which is a MySecret class.
TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can access MySecret
textView.setText(MySecret.getSecret());
Implementation (option #1)

If you're using implementation configuration, MySecret is not exposed.
TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can NOT access MySecret
textView.setText(MySecret.getSecret()); // Won't even compile
So, which configuration you should choose? That really depends on your requirement. 
If you want to expose dependencies use api or compile. 
If you don't want to expose dependencies (hiding your internal module) then use implementation.
Note:
This is just a gist of Gradle configurations, refer to Table 49.1. Java Library plugin - configurations used to declare dependencies for more detailed explanation.
The sample project for this answer is available on https://github.com/aldoKelvianto/ImplementationVsCompile